3

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

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

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

这与浏览器的版本无关,因为它可以在某些机器上运行,而不能在具有相同版本的其他机器上运行。此外,拥有两台相同设置的机器,有时会发生在一台机器上,但从不会发生在另一台机器上。所以总的来说,会议似乎发生了一些非常非常奇怪的事情,但我完全不知道该去哪里看。在过去几个月的大部分时间里,我一直在尝试对此进行调查,但一无所获。还有哪里可以看?

在这一点上,任何帮助都非常感激。

添加:这是我的 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
4

1 回答 1

0

我遇到了相同的问题,会话在某些盒子上随机超时,在其他盒子上始终如一,而在大多数盒子上根本没有。经过大量的试验和错误,我将我的问题追溯到一些具有紧凑隐私策略问题的 IE 机器。我们只是添加了一个像这样的标题 header('P3P: CP=Visit www.oururl.tld for our Privacy Policy.'),它阻止了旧 IE 的很多问题。这应该只适用于 3rd 方 cookie,但谁知道 IE。

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

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

这三件事解决了所有问题,但我强烈怀疑是由于谷歌和雅虎工具栏对浏览器缓存或浏览器临时 Internet 文件本身做了奇怪的事情而导致的最不可重现的实例。

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

于 2012-10-31T17:32:19.163 回答