In our intranet application(s) we use SSO (single sign on) login while the sessions both on client and auth origin applications are stored in memcached.
The sessions are set to live for 12h before the garbage collector may consider them as for removal. Both applications are written using ZF2.
Unfortunately, the problem is, that after certain period of time (I don't have the exact value) the browser loses the session which causes the redirection to auth origin, where the session is still alive thus user is redirected back to client and the browser session is refreshed. This is not a big deal if the user has no unsaved work as these two redirects happen within 1 second and user even may not notice them.
But it really is a big deal when user has unsaved work and even an attempt to save it leads to redirects and the work is gone.
Here is the configuration of session in Bootstrap.php
:
class Module
{
public function onBootstrap(MvcEvent $e)
{
// ...
$serviceManager = $e->getApplication()->getServiceManager();
$sessionManager = $serviceManager->get('session_manager_memcached');
$sessionManager->start();
Container::setDefaultManager($sessionManager);
// ...
}
public function getServiceConfig()
{
return array(
'factories' => array(
// ...
'session_manager_memcached' => function ($sm) {
$systemConfig = $sm->get('config');
$config = new SessionConfig;
$config->setOptions(array(
'phpSaveHandler' => 'memcache',
'savePath' => 'tcp://localhost:11211?timeout=1&retry_interval=15&persistent=1',
'cookie_httponly' => true,
'use_only_cookies' => true,
'cookie_lifetime' => 0,
'gc_maxlifetime' => 43200, // 12h
'remember_me_seconds' => 43200 // 12h
));
return new SessionManager($config);
},
// ...
);
}
}
The authentication service is defined as
'authService' => function ($sm) {
$authService = new \Zend\Authentication\AuthenticationService;
$authService->setStorage(new \Zend\Authentication\Storage\Session('user_login'));
return $authService;
},
Then anywhere within the application a session value needs to be retrieved or set I just use a \Zend\Session\Container
like this:
$sessionContainer = new \Zend\Session\Container('ClientXYZ');
$sessionContainer['key1'] = $val1;
// or
$val2 = $sessionContainer['key2'];
The SSO is requested for the active session at any action using the token from session which contains PHPSESSID from the auth origin. It's quite complicated to describe here within this question.
Additionally an authentication service stores a user identity (with roles for ACL) also in memcached session - using the same settings. Obviously this is now the place which causes confusion. Apparently the session storage of authentication service times out prematurely causing the ACL to retrieve no user identity to check leading into SSO logout sequence (but because user didn't really log out, SSO redirects the user back as described above).
I'm not sure how much code should I (and can I) share here, maybe you'll lead me to the solution straight away or just by asking me some questions. I am quite helpless right now after many hours of debugging and trying to identify the problem.
Somewhere I have read that memcached wipes out the memory once the session cookie gets 1MB in size - may this be the case? For the user identity we save just general user information and array of roles, I'd guess this could be max. up to few kb in size...
EDIT 1: To dismiss all guesses and to save your time, here few facts (to keep an eye on):
PHPSESSID
between the browser and server and it's value is the key for memory chunk in memcached where the data is storedI am going to implement some die
s in PHP and return
s in JS parts to catch the moment when the session is considered gone and further inspect the browser cookie, memcached data, etc. and will update you (unless somebody comes with explanation and solution).
public function initSession()
{
$sessionConfig = new SessionConfig();
$sessionConfig->setOptions([
'cookie_lifetime' => 7200, //2hrs
'remember_me_seconds' => 7200, //2hrs This is also set in the login controller
'use_cookies' => true,
'cache_expire' => 180, //3hrs
'cookie_path' => "/",
'cookie_secure' => Functions::isSSL(),
'cookie_httponly' => true,
'name' => 'cookie name',
]);
$sessionManager = new SessionManager($sessionConfig);
// $memCached = new StorageFactory::factory(array(
// 'adapter' => array(
// 'name' =>'memcached',
// 'lifetime' => 7200,
// 'options' => array(
// 'servers' => array(
// array(
// '127.0.0.1',11211
// ),
// ),
// 'namespace' => 'MYMEMCACHEDNAMESPACE',
// 'liboptions' => array(
// 'COMPRESSION' => true,
// 'binary_protocol' => true,
// 'no_block' => true,
// 'connect_timeout' => 100
// )
// ),
// ),
// ));
// $saveHandler = new Cache($memCached);
// $sessionManager->setSaveHandler($saveHandler);
$sessionManager->start();
return Container::setDefaultManager($sessionManager);
}
This is the function I use in order to create a cookie for X user. The cookie lives for 3 hours, no matter if there are redirects or if the user has closed the browser. It's still there. Just call this function in your onBootstrap() method from Module.php.
While logging, I use The ZF2 AuthenticationService and the Container to store and retrieve the user data.
I suggest you to install these module for easier debugging. https://github.com/zendframework/ZendDeveloperTools https://github.com/samsonasik/SanSessionToolbar/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With