ZF2:如何实现会话超时和会话固定修复

时间:2014-05-11 04:33:28

标签: php session zend-framework2 session-fixation

我希望我的会话在30分钟不活动后过期,但是当我设置它时,我的用户会随机退出,即使他们可能只有几秒钟不活动。我认为问题在于重新生成会话ID。

我的理解是,为了获得理想的效果,我需要在会话中将remember_me_seconds配置为1800.然后在我的引导程序中,在我调用$sessionMgr->start()之后,我需要调用$sessionMgr->rememberMe()

rememberMe()来电regenerateId(),我认为这就是问题所在。我认为如果浏览器快速连续发出两个请求,则会处理第一个请求,并在服务器上更新会话ID。当服务器收到第二个请求时,它仍然带有旧的会话ID,该会话ID不再被识别,因此服务器会将您视为已注销。听起来有可能吗?我认为一定是这样,因为我可以通过直接调用regenerateId()来模拟问题(而不是调用rememberMe()

那么,问题是我应该如何实现我想要的解决方案?就会话超时而言,我可以存储最后一次访问'我的会话中的时间,并在收到请求时将其与当前时间进行比较。但这会使rememberMe()功能变得多余。至于重新生成id以避免会话固定,我无法看到我如何有效地做到这一点。总会出现快速连续存在多个浏览器请求的情况,因此服务器可能会失去同步......

2 个答案:

答案 0 :(得分:2)

对于会话超时,您可以执行以下操作。我在每个控制器扩展的类中都有这个,并且这个超时方法在每个请求上运行。此外,超时值最初是在登录时设置的。

/**
 * If user is inactive for 5 minutes, log them out.
 * 
 * @return void | Zend\Mvc\Controller\Plugin\Redirect
 */
protected function timeout()
{
    // User Active so reset time session. (5minutes)
    // Note: (I'm using $this->identity which is basically an Auth object)
    // but would work the same way as $_SESSION['timeout']
    if ($this->identity->timeout + 300 > time()) 
    {
        $this->identity->timeout = time();
    } 

    // session timed out, logout user
    // this routes to the location of destroying the session, etc.
    else 
    {   
        return $this->redirect()->toRoute('logout', array());
    }       
} 

此外,如果您想要在不刷新页面的情况下自动注销用户,那么您可能希望在重置(n)秒后使用AJAX检查超时值。

防止会话固定: 我还没有在ZF2中实现它。但是我在ZF1中做了,它运行良好没有任何问题。我知道那确实没有给你一个答案,但是我会假设同样的东西也可以在ZF2中起作用。

随机退出: 我在一些应用程序中看到过,通过更改php.ini文件中的某些会话属性来修复此问题。在另一个应用程序中,我目前正在使用ZF2' rememberMe($time),没有任何问题。

查看如何设置会话存储选项和初始化会话命名空间对象可能也会有所帮助。在Zend\Session\Container中,请注意文档块:

/**
 * Session storage container
 *
 * Allows for interacting with session storage in isolated containers, which
 * may have their own expiries, or even expiries per key in the container.
 * Additionally, expiries may be absolute TTLs or measured in "hops", which
 * are based on how many times the key or container were accessed.
 */

这样的事情:

$this->session = new SessionContainer($this->namespace, $manager);

设置rememberMe:

$this->session->getManager()->rememberMe($time);

希望这能指明你正确的方向。

答案 1 :(得分:0)

好的,所以我从错误的角度来看这个。我曾假设“记住我”和“cookie生命周期”旨在帮助会话超时。正如这个问题清楚地表明How do I expire a PHP session after 30 minutes?,我应该实现自己的解决方案。

此外,在阅读本文http://phpsec.org/projects/guide/4.html后,我可以看到我只需要在用户登录或注销时重新生成会话ID。