memcached中的ZF2身份验证会话存储

sha*_*yyx 9 php authentication session memcached zend-framework2

在我们的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);
                },
                // ...
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

身份验证服务定义为

            'authService' => function ($sm) {
                $authService = new \Zend\Authentication\AuthenticationService;
                $authService->setStorage(new \Zend\Authentication\Storage\Session('user_login'));
                return $authService;
            },
Run Code Online (Sandbox Code Playgroud)
  • 会话存储使用相同的memcached会话管理器.

然后在应用程序中的任何地方都需要检索或设置会话值我只需使用\Zend\Session\Container如下:

$sessionContainer = new \Zend\Session\Container('ClientXYZ');
$sessionContainer['key1'] = $val1;
// or
$val2 = $sessionContainer['key2'];
Run Code Online (Sandbox Code Playgroud)

在使用来自会话的令牌的任何操作中,请求活动会话使用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

我将die在PHP中实现一些s和returnJS部分中的s来捕捉会话被认为已经消失的时刻并进一步检查浏览器cookie,memcached数据等,并将更新你(除非有人提供解释和解决方案).

Jas*_*wer 1

Memcached 和 gc_maxlifetime

当使用memcachedas时session.save_handler,会话的垃圾收集将不会被完成。

由于 Memcached 使用 TTL(生存时间)值,因此不需要垃圾回收。生存时间不够长而未达到 TTL 年龄的条目将被视为“新鲜”并将被使用。之后它将被视为“陈旧”并且将不再使用。最终 Memcached 会释放该条目所使用的内存,但这与 PHP 的会话垃圾回收无关。

事实上,session.gc_本例中实​​际使用的唯一设置是session.gc_maxlifetime,它将作为 TTL 传递到 Memcached。

简而言之:垃圾收集在您的情况下不是问题。

Memcached 和 Cronjobs

当您使用 Memcached 作为会话存储时,操作系统提供的任何手动清理磁盘上会话文件夹的 cronjobs(如 Ubuntu 那样)都将无效。Memcached 是内存存储,而不是磁盘存储。

简而言之:像这样的 cronjobs 在您的情况下不是问题。

应用程序问题,而不是 SSO

您声明 SSO 服务器/权限与 SSO 客户端(应用程序本身)位于同一台计算机上,使用相同的 Web 服务器/PHP 配置,并且使用相同的 Memcached 实例。

这让我相信我们必须研究如何在应用程序中完成会话管理,因为这是 SSO 权限和客户端之间的唯一区别。换句话说:我们需要深入研究 Zend\Session。

免责声明:我曾专业开发过多个 Zend Framework 1 应用程序,但没有开发过任何 Zend Framework 2 应用程序。所以我在这里盲目飞行:)

配置

我在您的配置中注意到的一件事是您已设置cookie_lifetime0. 这实际上意味着“直到浏览器关闭”。这与设置为 12 小时并没有什么意义remember_me_seconds,因为很多人会在此之前关闭浏览器。

我建议你cookie_lifetime也设置为12小时。

另请注意,remember_me_seconds仅在实际使用“记住我”功能时使用。换句话说: ifZend\Session\SessionManager::rememberMe()被调用。

替代实施

看看您使用 Memcached 作为会话存储实现的方式,以及我在该主题上可以找到的内容,我想说您所做的事情与似乎“首选方式”不同。

关于此主题的大多数资源建议使用Zend\Session\SaveHandler\Cache( doc , api ) 作为保存处理程序,这使您能够使用Zend\Cache\Storage\Adapter\Memcached( doc , api )。这使您可以更好地控制正在发生的事情,因为它不依赖于有限的memcached会话保存处理程序。

我建议你尝试这个实现。如果它不能立即解决您的问题,至少还有更多关于该主题的资源可以找到。恕我直言,您找到解决方案的机会会更大。