[英]ZF2 authentication session storage in memcached
在我們的Intranet應用程序中,我們使用SSO(單點登錄)登錄,而客戶端和auth源應用程序上的會話都存儲在memcached中。
會話設置為在垃圾收集器可能將其視為刪除之前的12小時。 兩個應用程序都是使用ZF2編寫的。
不幸的是,問題是,在一段時間后(我沒有確切的值),瀏覽器會丟失導致重定向到auth origin的會話,其中會話仍處於活動狀態,因此用戶被重定向回客戶端並且瀏覽器會話刷新。 如果用戶沒有未保存的工作,這不是什么大問題,因為這兩個重定向在1秒內發生,用戶甚至可能不會注意到它們。
但是當用戶有未保存的工作時,它確實是一個大問題,即使嘗試保存它也會導致重定向,工作也就消失了。
以下是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);
},
// ...
);
}
}
身份驗證服務定義為
'authService' => function ($sm) {
$authService = new \Zend\Authentication\AuthenticationService;
$authService->setStorage(new \Zend\Authentication\Storage\Session('user_login'));
return $authService;
},
然后在應用程序中的任何地方都需要檢索或設置會話值我只需使用\\Zend\\Session\\Container
如下所示:
$sessionContainer = new \Zend\Session\Container('ClientXYZ');
$sessionContainer['key1'] = $val1;
// or
$val2 = $sessionContainer['key2'];
在使用來自會話的令牌的任何操作中,請求活動會話使用SSO,該會話包含來自auth源的PHPSESSID。 在這個問題中描述這個很復雜。
此外,身份驗證服務還使用相同的設置在memcached會話中存儲用戶身份(具有ACL的角色)。 顯然,現在這是造成混亂的地方。 顯然,身份驗證服務的會話存儲過早地超時導致ACL不檢索用戶身份以檢查導致SSO注銷序列(但由於用戶沒有真正注銷,SSO如上所述重定向用戶)。
我不確定我(也可以)在這里分享多少代碼,也許你會立即引導我解決問題,或者只是問我一些問題。 經過數小時的調試並試圖找出問題后,我現在很無助。
在某個地方,我已經讀過,一旦會話cookie的大小達到1MB,memcached就會擦掉內存 - 可能就是這種情況嗎? 對於用戶身份,我們只保存一般用戶信息和角色陣列,我猜這可能是最大的。 高達幾kb ...
編輯1:要消除所有猜測並節省您的時間,這里有一些事實(要密切關注):
PHPSESSID
,它的值是memcached中存儲數據的內存塊的關鍵 我將在PHP中實現一些die
,並在JS部件中return
s以捕獲會話被認為消失的時刻並進一步檢查瀏覽器cookie,memcached數據等,並將更新您(除非有人提供解釋和解決方案) )。
當使用memcached
作為session.save_handler
,將不會進行會話的垃圾收集。
因為Memcached使用TTL(生存時間)值,所以不需要垃圾收集。 沒有足夠長的時間達到TTL年齡的條目將被視為“新鮮”並將被使用。 之后,它會被視為“過時”,並且不會再使用。 最終,Memcached將釋放條目使用的內存,但這與PHP的會話垃圾收集無關。
事實上,在這種情況下實際使用的唯一session.gc_
設置是session.gc_maxlifetime
,它將作為TTL傳遞給Memcached。
簡而言之:在您的情況下,垃圾收集不是問題。
當您使用Memcached作為會話的存儲時,操作系統提供的任何手動清理磁盤上的會話文件夾(如Ubuntu)的cronjobs將不起作用 。 Memcached是內存存儲,而不是磁盤存儲。
簡而言之:像這樣的cronjobs在你的情況下不是問題。
您聲明SSO服務器/授權與SSO客戶端(應用程序本身)在同一台機器上,使用相同的Web服務器/ PHP配置,並使用相同的Memcached實例。
這讓我相信我們必須在應用程序中搜索會話管理的方式,因為這是SSO權限和客戶端之間的唯一區別。 換句話說:我們需要深入了解Zend \\ Session。
免責聲明:我已經專業地研究了幾個Zend Framework 1應用程序,但沒有在任何Zend Framework 2應用程序上工作。 所以我在這里盲目飛行:)
我在您的配置中注意到的一件事是您已將cookie_lifetime
設置為0
。 這實際上意味着“直到瀏覽器關閉”。 這與設置為12小時的remember_me_seconds
一起沒有意義,因為很多人會在此之前關閉瀏覽器。
我建議你將cookie_lifetime
設置為12小時。
另請注意, remember_me_seconds
僅在實際使用“記住我”功能時使用。 換句話說:如果調用Zend\\Session\\SessionManager::rememberMe()
。
看看你使用Memcached作為會話存儲實現的方式,以及我在這個主題上可以找到的內容,我會說你做了一些不同於“首選方式”的東西。
關於此主題的大多數資源建議使用Zend\\Session\\SaveHandler\\Cache
( doc , api )作為save-handler,這使您能夠使用Zend\\Cache\\Storage\\Adapter\\Memcached
( doc , api )。 這使您可以更好地控制正在發生的事情,因為它不依賴於有限的memcached
session-save-handler。
我建議你試試這個實現。 如果它不能立即解決您的問題,則至少需要更多資源才能找到該主題。 你找到解決方案的機會會更好恕我直言。
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);
}
這是我用來為X用戶創建cookie的函數。 無論是否有重定向或用戶是否關閉了瀏覽器,cookie都會存在3個小時。 它還在那里。 只需在Module.php的onBootstrap()方法中調用此函數即可。
在記錄時,我使用ZF2 AuthenticationService和Container來存儲和檢索用戶數據。
我建議你安裝這些模塊以便於調試。 https://github.com/zendframework/ZendDeveloperTools https://github.com/samsonasik/SanSessionToolbar/
這個答案可能不會立即解決你的memcache問題的原因,但由於memcache的不可靠性,我建議在一些持久存儲中備份你的memcached數據。 記憶數據將幫助您提高應用程序的性能,但它不是故障安全的。
也許您可以在AuthenticationService
實例中創建一個備用(持久)存儲。 然后首先嘗試從內存緩存中獲取身份驗證數據,如果找不到任何內容,則檢查持久性存儲中是否有可用內容。
這至少可以解決所有意外的memcache丟失問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.