如何在用户激活时继续延长会话寿命?

时间:2012-08-13 07:58:40

标签: php session session-cookies

假设有一个已登录成员区域的站点/系统,用户很少,但在使用站点/系统时非常不方便注销。

令人怀疑的是会话到期,因为用户很长时间没有空闲。即使它们处于空闲状态,我也添加了一个定期的AJAX请求,即所谓的心跳,它会更新会话的访问时间和修改时间。每次用户点击某个内容或调用心跳时,我甚至都添加了一个触摸($ session_file)。我也尝试重新生成会话ID。什么都没有帮助。

不幸的是,到目前为止,我无法在本地重现问题,因为当需求增加时,它经常发生。一些php.ini参数:

session.use_cookies = 1
session.use_only_cookies = 1
session.cookie_lifetime = 0
session.gc_probability = 1
session.gc_divisor = 1500
session.gc_maxlifetime = 10800

5 个答案:

答案 0 :(得分:6)

由于会话和身份验证已经通过代码中的一个超级控制器处理,因此至少应该排除会话破坏。

通常只有登录页面会创建一个会话,所以此时你可以(并且应该)在里面添加一个已知值,例如会话ID。

其他页面(包括您的心跳)恢复现有会话,因此此时您将查找上述值;如果它丢失了,你可以再做一些检查:

  • 是会话cookie通过了吗?如果没有,浏览器/ cookie问题。
  • 会话Cookie是否与session_id()对应?如果没有,会话文件由于垃圾回收而丢失。
  • 会话中是否存在已知值?如果没有,会话被截断或有人试图进行会话采用攻击。
  • 已知值是否与会话cookie相对应?如果没有,会议是通过与cookie不同的方式建立的;你可以查看session.use_only_cookies设置。

上述检查应该指向正确的方向。

答案 1 :(得分:3)

我认为您使用的是内置的PHP文件会话存储?有已知的竞争条件问题。

当来自同一会话ID的并发请求时,我遇到了类似的问题,即丢失会话ID。由于文件被第一个请求锁定,所有其他并发连接都无法访问文件,其中一些生成了新的会话ID。这些情况也非常罕见,我花时间找到问题所在。从那时起,我正在使用memcached进行会话存储,这些问题就消失了。

答案 2 :(得分:2)

如果没有进一步的信息,我很难回答这个问题,但是你确定只有当你有更多的流量时才会这样做。可以做些什么:

  • 添加codez
  • OS发行版和版本
  • PHP版

您是否有任何依赖IP的会话检查。如果是这样,那么你实际上可能正在使用一个代理,每个代理都会提供一个不同的IP(如Cloudflare),在这种情况下你可以使用HTTP_CF_CONNECTING_IP来获得实际上不变的IP。

我还注意到了一件事:

session.use_only_cookies = 1
session.cookie_lifetime = 0

因此,当浏览器关闭时,cookie实际上将被销毁。是否有可能因用户关闭标签而丢失连接(在某些浏览器中确实清除了cookie)?

正如其他人所说,我会强烈地说你转到数据库会话。使用中央会话存储可以帮助阻止竞争条件,它不会完全阻止它们,但它确实使它变得更难。此外,如果你真的得到那么多会话id你可能想要使用内置的PHP会话ID以外的东西,但是内置的哈希是非常独特的,并且很有可能被复制,所以我不认为这是你的问题

澄清编辑:

如果您使用不同的Cloudflare代理,那么您当然需要获取代理集的HTTP标头,使用Cloudflare就是一个例子。

答案 3 :(得分:0)

这是我用过的东西。它使用javascript以10分钟的间隔“ping”服务器。

<form method="POST" target="keepalive-target" id="keepalive-form">
    <input type="hidden" name="keepalive-count" id="keepalive-count">
</form>
<iframe style="display:none; width:0px; height:0px;" name="keepalive-target"></iframe>
<script>
    var kaCount=0;
    setInterval(function()
    {
        document.getElementById("keepalive-count").value=kaCount++
        document.getElementById("keepalive-form").submit();
    },600000);
</script>

答案 4 :(得分:0)

所有提供的答案都显示了对问题的良好洞察力,但我只需要分享解决方案以解决我的确切问题。我终于能够重现问题并修复它。

所以系统包含两个子系统,比如说管理员和客户端接口。当管理员以另一个选项卡中的客户端登录并在以管理员身份登录时注销客户端界面时,管理员意外注销。这样做是因为所有内容都写入了一个带有命名空间的会话。我所做的是删除在注销操作中一直销毁会话的代码,并将其替换为会话命名空间取消设置,并替换为只能访问登录页面的该命名空间的访客会话。