簡體   English   中英

memcached中的ZF2身份驗證會話存儲

[英]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;
            },
  • 會話存儲使用相同的memcached會話管理器。

然后在應用程序中的任何地方都需要檢索或設置會話值我只需使用\\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:要消除所有猜測並節省您的時間,這里有一些事實(要密切關注):

  • 只使用memcached
  • cookies僅用於在瀏覽器和服務器之間傳輸PHPSESSID ,它的值是memcached中存儲數據的內存塊的關鍵
  • 客戶端和SSO auth應用程序在一台服務器上運行(無論是集成,登台還是實時環境,還只是一台服務器)
  • 客戶端應用程序上的會話隨機關閉,導致它重定向到SSO auth應用程序,但此處會話仍處於活動狀態,因此用戶被重定向回客戶端應用程序,獲取新會話並且用戶保持登錄狀態
  • 這應該忽略關於memcached被擦除或重新啟動的討論
  • 對telneted memcached的觀察直接顯示兩個數據塊(對於客戶端和auth應用程序)幾乎同時建立與相同的ttl

我將在PHP中實現一些die ,並在JS部件中return s以捕獲會話被認為消失的時刻並進一步檢查瀏覽器cookie,memcached數據等,並將更新您(除非有人提供解釋和解決方案) )。

Memcached&gc_maxlifetime

當使用memcached作為session.save_handler ,將不會進行會話的垃圾收集。

因為Memcached使用TTL(生存時間)值,所以不需要垃圾收集。 沒有足夠長的時間達到TTL年齡的條目將被視為“新鮮”並將被使用。 之后,它會被視為“過時”,並且不會再使用。 最終,Memcached將釋放條目使用的內存,但這與PHP的會話垃圾收集無關。

事實上,在這種情況下實際使用的唯一session.gc_設置是session.gc_maxlifetime ,它將作為TTL傳遞給Memcached。

簡而言之:在您的情況下,垃圾收集不是問題。

Memcached&Cronjobs

當您使用Memcached作為會話的存儲時,操作系統提供的任何手動清理磁盤上的會話文件夾(如Ubuntu)的cronjobs將不起作用 Memcached是內存存儲,而不是磁盤存儲。

簡而言之:像這樣的cronjobs在你的情況下不是問題。

發布應用程序,而不是SSO

您聲明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\\Cachedocapi )作為save-handler,這使您能夠使用Zend\\Cache\\Storage\\Adapter\\Memcacheddocapi )。 這使您可以更好地控制正在發生的事情,因為它不依賴於有限的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM