简体   繁体   English

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

[英]How to keep extending session life when user is active?

Let's say there's a site/system with a logged in member area, and users are rarely, but very inconveniently logged out while working with the site/system. 假设有一个已登录成员区域的站点/系统,用户很少,但在使用站点/系统时非常不方便地注销。

It's doubtfully session expiring, since the user was not idle for very long. 由于用户没有闲置很长时间,因此会议到期。 And even if they were idle, I added a periodic AJAX request, a so called heartbeat, which updates the sessions' access time, and modified time. 即使它们处于空闲状态,我也添加了一个定期的AJAX请求,即所谓的心跳,它会更新会话的访问时间和修改时间。 I even added a touch($session_file) every time a user clicks something or a heartbeat is called. 每次用户点击某个内容或调用心跳时,我甚至都添加了一个触摸($ session_file)。 I tried regenerating session ID as well. 我也尝试重新生成会话ID。 Nothing helped. 什么都没有帮助。

And unfortunately, so far, I was not able to reproduce the problem locally, because it happens every so often, when there's more requests. 不幸的是,到目前为止,我无法在本地重现问题,因为当需求增加时,它经常发生。 Some php.ini parameters: 一些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

Since sessions and authentication is already handled via one super controller in your code, it should be easy to at least rule out session destruction. 由于会话和身份验证已经通过代码中的一个超级控制器处理,因此至少应该排除会话破坏。

Typically only the login page creates a session, so at this point you can (and should) add a known value inside, such as the session id. 通常只有登录页面会创建会话,因此此时您可以(并且应该)在内部添加已知值,例如会话ID。

The other pages (including your heartbeat) resume an existing session, so at this point you look for the above value; 其他页面(包括您的心跳)恢复现有会话,因此此时您将查找上述值; if it's missing, you can do a few more checks: 如果它丢失了,你可以再做一些检查:

  • was a session cookie passed? 会话cookie是通过了吗? if not, browser / cookie issue. 如果没有,浏览器/ cookie问题。
  • does the session cookie correspond with session_id() ? 会话cookie是否与session_id()对应? if not, session file was lost due to garbage collection. 如果没有,会话文件由于垃圾收集而丢失。
  • does the known value exist in the session? 会话中是否存在已知值? if not, session was truncated or someone is trying to do session adoption attack. 如果没有,会话被截断或有人试图进行会话采用攻击。
  • does the known value correspond to the session cookie? 已知值是否与会话cookie相对应? if not, the session was established via different means than cookie; 如果没有,会议是通过与cookie不同的方式建立的; you could check session.use_only_cookies setting. 你可以查看session.use_only_cookies设置。

The above set of checks should point you in the right direction. 上述检查应该指向正确的方向。

I presume you are using built in PHP file session storage? 我假设你使用内置的PHP文件会话存储? There are known race conditions problems with it. 有已知的竞争条件问题。

I had similar issues with loosing session id's when there were concurrent requests from same session id. 当来自同一会话ID的并发请求时,我遇到类似的问题,即丢失会话ID。 Since file was locked by first request all other concurrent connections were unable to access file and some of them generated new session id. 由于文件被第一个请求锁定,所有其他并发连接都无法访问文件,其中一些生成了新的会话ID。 Those situations were also very rare and it took me time to locate the problem. 这些情况也非常罕见,我花时间找到问题所在。 Since then I'm using memcached for session storage and those problems vanished. 从那时起,我正在使用memcached进行会话存储,这些问题就消失了。

It is hard for me to answer this without further information however are you sure this only happens when you have more traffic. 如果没有进一步的信息,我很难回答这个问题,但是你确定只有当你有更多的流量时才会这样。 What can be done: 可以做些什么:

  • Add the codez 添加codez
  • OS distro and version OS发行版和版本
  • PHP version PHP版本

Do you have any session checks that rely on the IP. 您是否有任何依赖IP的会话检查。 If so it might be that you are actually using a proxy which gives a different IP once every so oftern (like Cloudflare) in which case you can use the HTTP_CF_CONNECTING_IP to get the actually constant IP. 如果是这样,那么你实际上可能正在使用一个代理,每个代码都会提供一个不同的IP(如Cloudflare),在这种情况下你可以使用HTTP_CF_CONNECTING_IP来获得实际上不变的IP。

I have also noticed one more thing: 我还注意到了一件事:

session.use_only_cookies = 1
session.cookie_lifetime = 0

So the cookie will actually be destroyed when the browser closes. 因此,当浏览器关闭时,cookie实际上将被销毁。 Is it possible the connection is lost because the user closes the tab (which in some browsers does actually clear the cookies)? 是否可能因用户关闭选项卡而丢失连接(在某些浏览器中确实会清除cookie)?

As others have suggested I would strongely say you move to a DB session. 正如其他人所建议的那样,我会强烈地说你转到数据库会话。 Using a central session store can help in stopping race conditions, it won't stop them completely but it does make it harder. 使用中央会话存储可以帮助阻止竞争条件,它不会完全阻止它们,但它确实使它更难。 Also if you really get that many session ids you might wanna look into using something other than the built in PHP session id, however the built in hash is extremely unique and has a very low chance of being duplicate so I don't think that's your problem. 此外,如果你真的得到那么多会话id你可能想要使用内置的PHP会话ID以外的东西,但是内置的哈希是非常独特的,并且很有可能被复制,所以我不认为这是你的问题。

Clarification Edit: 澄清编辑:

If you are using a different proxy to Cloudflare then you will, of course, need to get the HTTP header thart your proxy sets, using Cloudflare is an example. 如果您使用不同的Cloudflare代理,那么您当然需要获取代理集的HTTP标头,使用Cloudflare就是一个例子。

Here's something I've used. 这是我用过的东西。 It uses javascript to 'ping' the server on an interval of 10 minutes. 它使用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>

All the provided answers have shown good insight to the question, but I just have to share the solution to my exact problem. 所有提供的答案都显示了对问题的良好洞察力,但我只需要与我的确切问题分享解决方案。 I was finally able to reproduce the problem and fix it. 我终于能够重现问题并修复它。

So the system contained two subsystems, let's say admin and client interfaces. 所以系统包含两个子系统,比如说管理员和客户端接口。 The admin was unexpectedly logged out when they logged in as client in another tab and logged out the client interface while being logged in as admin. 当管理员以另一个选项卡中的客户端登录并在以管理员身份登录时注销客户端界面时,管理员意外注销。 It was doing this because everything was written to one session with namespaces. 这样做是因为所有内容都写入了一个带有命名空间的会话。 What I did is remove the code that kept destroying the session on logout action, and replaced it with session namespace unsetting and replacing with guest session for that namespace that only has access to the login page. 我所做的是删除在注销操作中一直销毁会话的代码,并将其替换为会话命名空间取消设置,并替换为只能访问登录页面的该命名空间的访客会话。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM