奇怪,烦人且非常随机的会话超时

时间:2012-04-19 10:13:22

标签: php session-timeout

我有一个相当大的PHP应用程序(数千个唯一的URL,具有各种角色的用户登录等).PHP在php.ini中将会话超时设置为1小时(3600秒)。登录的工作方式是:当用户成功登录应用程序时,有关用户的一些内容存储在$ _SESSION中,包括用户名,真实姓名,角色ID等。在每个页面访问(公共代码),$检查_SESSION是否存在这些变量,如果存在,则用户会前往他们要求的位置。如果变量不存在,则将用户重定向到“未登录”页面。

这在过去几年一直运作良好,并且仍然运作良好 - 主要是。非常随机的会话似乎超时而没有任何警告或其他任何事情。对于已登录的用户,可以这样看:登录,执行某些操作,导航到下一页 - 然后退出并返回“未登录”页面。当然,这非常烦人。然而,这种行为的随机性使得调查变得非常困难。

我从未在任何浏览器的机器上体验过它。办公室里还有另一台机器,这种情况一直发生在每个浏览器中(至少我可以重现这个问题)。在另一台机器上,它发生在一个浏览器中,而不是在另一个浏览器中发生。然而在另一台机器上它有时会发生而不是其他时间。今天我们接到一位遇到此问题的客户的电话 - 但是当要求在不同的浏览器中尝试时,它运行正常。

这不是由于浏览器的版本,因为它适用于某些机器,而不适用于具有相同版本的其他机器。此外,有两个相同设置的机器,它有时发生在一个,但从来没有在另一个。总的来说,似乎会议中发生了一些非常奇怪的事情,但我对于在哪里看起来感到非常难过。在过去的几个月里,我一直试图对此进行调查,但是没有得到任何结果。还有什么地方可以看?

此时任何帮助都非常受欢迎。

ADDED:以下是我的php.ini的会话部分:

[Session]
session.save_handler = files
session.use_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly = 
session.serialize_handler = php
session.gc_divisor     = 100
session.gc_maxlifetime = 3600 
session.bug_compat_42 = 1
session.bug_compat_warn = 1
session.referer_check =
session.entropy_length = 0
session.entropy_file =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 4

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,会话在某些方框上随机排除,在其他方面一致,而在大多数情况下根本没有。经过大量的试验和错误后,我将我的问题追溯到一些机器,其中IE具有紧凑的隐私政策问题。我们只是添加了一个像标题一样的标题(' P3P:CP =访问www.oururl.tld我们的隐私政策。'),它阻止了旧IE的许多问题。这只适用于第三方cookie,但谁知道IE。

其次,我发现有些机器在.domain.tld上设置会话cookie然后从domain.tld而不是www.domain.tld访问它时适合。确保所有请求都被定向到www子域解决了大多数其他浏览器。

最后,我不得不从php接管设置会话超时,因为我们服务器的时区在自动设置时导致了问题。我只是将到期时间设置为0,这样它就不会使用浏览器超时使用cookie,直到" session"用户关闭浏览器等结束。然后我在会话中添加了一个简单的expires变量并手动检查它,以便所有关于到期的检查和决定都是在我们服务器的时区进行的,而不是客户端。

这三件事情解决了所有但不可重复的实例,我强烈怀疑这些实例是由谷歌和雅虎工具栏等浏览器缓存或浏览器临时互联网文件本身造成的。

如果您使用会话ID重新生成和AJAX /其他异步调用,您可能还需要检查并确保没有遇到任何竞争条件。通常在较旧的浏览器中,当您重新生成id时,cookie根本不会足够快地更新,甚至更新的浏览器时间恰好足以提交带有新请求的旧ID并导致会话丢失。我最好的解决方案是不在AJAX上重新生成会话ID,而只是在实际的页面加载上,以便保持同步。还有其他几种方法,比如保留旧的会话数据而不是自动删除它(也只是在某种程度上不安全,只有您的应用程序的需求才能确定)。