Use local cache by default for tokens (#1140)

This commit is contained in:
Xavier Guimard 2017-03-11 18:11:57 +00:00
parent 435e20491e
commit 81d3729394
12 changed files with 117 additions and 29 deletions

View File

@ -2890,6 +2890,10 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
},
'type' => 'int'
},
'tokenUseGlobalStorage' => {
'default' => 0,
'type' => 'bool'
},
'trustedDomains' => {
'type' => 'text'
},

View File

@ -430,6 +430,11 @@ sub attributes {
type => 'bool',
documentation => 'Enable token for forms',
},
tokenUseGlobalStorage => {
default => 0,
type => 'bool',
documentation => 'Enable global token storage',
},
cda => {
default => 0,
type => 'bool',

View File

@ -638,6 +638,7 @@ sub tree {
},
'requireToken',
'formTimeout',
'tokenUseGlobalStorage',
]
},
{

View File

@ -646,6 +646,7 @@
"timeout": "Sessions timeout",
"timeoutActivity": "Sessions activity timeout",
"timeoutActivityInterval": "Sessions update interval",
"tokenUseGlobalStorage": "Use global storage",
"trustedDomains": "Trusted domains",
"trustedProxies": "Trusted proxies IP",
"twitterAppName": "Application name",

View File

@ -646,6 +646,7 @@
"timeout": "Durée de vie maximale des sessions",
"timeoutActivity": "Délai d'expiration des sessions",
"timeoutActivityInterval": "Intervalle de mise à jour des sessions",
"tokenUseGlobalStorage": "Utiliser le cache global",
"trustedDomains": "Domaines approuvés",
"trustedProxies": "IP des proxys de confiance",
"twitterAppName": "Nom de l'application",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,7 @@ package Lemonldap::NG::Portal::Lib::OneTimeToken;
use strict;
use Mouse;
use JSON qw(from_json to_json);
our $VERSION = '2.0.0';
@ -14,6 +15,30 @@ has timeout => (
}
);
has cache => (
is => 'rw',
default => sub {
my $c = $_[0]->{conf};
if ( !$c->{tokenUseGlobalStorage} ) {
if ( $c->{localSessionStorage} ) {
eval "use $c->{localSessionStorage}";
if ($@) {
$_[0]->{p}->logger->error($@);
return undef;
}
return $c->{localSessionStorage}
->new( $c->{localSessionStorageOptions} );
}
else {
$_[0]->{p}->logger->error(
'Local storage not defined, token will be store in global storage'
);
return undef;
}
}
},
);
sub createToken {
my ( $self, $infos ) = @_;
@ -33,10 +58,20 @@ sub createToken {
# Store type
$infos->{_type} ||= "token";
# Create a new session
my $tsession = $self->p->getApacheSession( undef, info => $infos );
if ( $self->cache ) {
my $id = $infos->{_utime} . '_' . int( rand(10000) );
return $tsession->id;
# Dereference $infos
my %h = %$infos;
$self->cache->set( $id, to_json( \%h ) );
return $id;
}
else {
# Create a new session
my $tsession = $self->p->getApacheSession( undef, info => $infos );
return $tsession->id;
}
}
sub getToken {
@ -46,15 +81,33 @@ sub getToken {
return undef;
}
# Get token session
my $tsession = $self->p->getApacheSession($id);
unless ($tsession) {
$self->logger->notice("Bad (or expired) token $id");
return undef;
if ( $self->cache ) {
my $data;
my @t = split /_/, $id;
if ( $t[0] > time ) {
$self->logger->notice("Expired token $id");
$self->cache->remove($id);
return undef;
}
unless ( $data = $self->cache->get($id) ) {
$self->logger->notice("Bad (or expired) token $id");
return undef;
}
$self->cache->remove($id);
return from_json($data);
}
else {
# Get token session
my $tsession = $self->p->getApacheSession($id);
unless ($tsession) {
$self->logger->notice("Bad (or expired) token $id");
return undef;
}
my %h = %{ $tsession->{data} };
$tsession->remove;
return \%h;
}
my %h = %{ $tsession->{data} };
$tsession->remove;
return \%h;
}
sub setToken {

View File

@ -39,8 +39,9 @@ SKIP: {
# Try to get captcha value
my ( $ts, $captcha );
ok( $ts = $client->p->getApacheSession($token), ' Found token session' );
ok( $captcha = $ts->data->{captcha}, ' Found captcha value' );
ok( $ts = getCache()->get($token), ' Found token session' );
$ts = eval { JSON::from_json($ts) };
ok( $captcha = $ts->{captcha}, ' Found captcha value' );
# Try to authenticate
$query .= "&user=dwho&password=dwho&captcha=$captcha";

View File

@ -49,8 +49,9 @@ s/^.*token=([^&]+).*$/token=$1&firstname=foo&lastname=bar&mail=foobar%40badwolf.
# Try to get captcha value
my ( $ts, $captcha );
ok( $ts = $client->p->getApacheSession($token), ' Found token session' );
ok( $captcha = $ts->data->{captcha}, ' Found captcha value' );
ok( $ts = getCache()->get($token), ' Found token session' );
$ts = eval { JSON::from_json($ts) };
ok( $captcha = $ts->{captcha}, ' Found captcha value' );
$query .= "&captcha=$captcha";

View File

@ -51,8 +51,9 @@ SKIP: {
# Try to get captcha value
my ( $ts, $captcha );
ok( $ts = $client->p->getApacheSession($token), ' Found token session' );
ok( $captcha = $ts->data->{captcha}, ' Found captcha value' );
ok( $ts = getCache()->get($token), ' Found token session' );
$ts = eval { JSON::from_json($ts) };
ok( $captcha = $ts->{captcha}, ' Found captcha value' );
$query .= "&captcha=$captcha";

View File

@ -42,6 +42,18 @@ sub clean_sessions {
}
}
}
my $cache = getCache();
$cache->clear;
}
sub getCache {
return Cache::FileCache->new(
{
namespace => 'lemonldap-ng-session',
cache_root => 't/',
cache_depth => 0,
}
);
}
sub expectRedirection {
@ -211,15 +223,23 @@ use Mouse;
extends 'Lemonldap::NG::Common::PSGI::Cli::Lib';
our $defaultIni = {
configStorage => { type => 'File', dirName => 't' },
localSessionStorage => '',
logLevel => 'error',
cookieName => 'lemonldap',
domain => 'example.com',
templateDir => 'site/templates',
staticPrefix => '/index.fcgi',
securedCookie => 0,
https => 0,
configStorage => {
type => 'File',
dirName => 't',
},
localSessionStorage => 'Cache::FileCache',
localSessionStorageOptions => {
namespace => 'lemonldap-ng-session',
cache_root => 't/',
cache_depth => 0,
},
logLevel => 'error',
cookieName => 'lemonldap',
domain => 'example.com',
templateDir => 'site/templates',
staticPrefix => '/index.fcgi',
securedCookie => 0,
https => 0,
};
has app => (
@ -273,7 +293,7 @@ sub logout {
'Logout request'
);
main::ok( $res->[0] == 200, ' Response is 200' )
or explain( $res->[0], 200 );
or main::explain( $res->[0], 200 );
my $c;
main::ok(
( defined( $c = main::getCookies($res)->{lemonldap} ) and not $c ),