我在运行的PHP网站遇到问题,几分钟后用户正在注销(确切的时间会有所不同,但经常会出现问题),无论他们是否积极参与是否使用该网站。
困难在于我无法重现这个问题,如果我使用相同的浏览器登录相同的用户我没有注销,这表明这不是网站完全被破坏的情况。不幸的是,我无法访问用户计算机来运行任何流量嗅探软件。
我已经检查过的事情是:
PHP中的会话设置是Debian默认值,并且未在.htaccess文件或其他任何位置更改。主要是:
session.cookie_lifetime 0
session.gc_divisor 100
session.gc_maxlifetime 1440
session.gc_probability 0
session.save_handler files
session.save_path /var/lib/php5
session.use_cookies On
Debian通过cron作业删除会话而不是使用PHP的垃圾收集器,这就是为什么gc_probability被设置为0.我们运行的PHP版本是:PHP 5.2.6-1 + lenny13与Suhosin-Patch 0.9.6.2 (cli)(Lenny的最新版本,我们很快就会升级到Squeeze,但我不认为这是导致问题的原因。)
我们使用Zend_Session来管理会话,并在每个页面上创建一次Zend_Session_Namespace实例,从而自动调用session_start()。通过在注销页面上调用Zend_Session :: destroy()来清除会话,因此用户应该注销的唯一方法是:
检查用户是否已登录的检查是:
有人可以提出我可以尝试的其他事项吗?
编辑:我根据评论留下的其他一些事情:
编辑2:基于人们提出的其他问题:
答案 0 :(得分:3)
Debian通过cron作业删除会话,而不是使用PHP的垃圾收集器
这很奇怪 - 在cron工作中运行的代码是什么?
我们在退出时删除了这一行
我建议您在会话过期/删除后2天保留此项(但在当前删除它时将其标记为已死)。此外,开始在Web服务器日志中记录会话ID。
答案 1 :(得分:1)
我认为你计算改变了
的价值session.gc_maxlifetime
我也遇到了同样的问题。我花了很多时间在上面,然后我问我的网络服务提供商,当他获得许可后,他改变了这个价值。现在它工作正常。
答案 2 :(得分:1)
是否有其他php应用程序在同一系统上运行(例如,在不同的vhost下?)?他们还在/ var / lib / php5中保存会话吗?
如果是这样,其中一个应用程序的会话垃圾回收阈值较低,它们会丢弃应用程序的会话文件。
我做了很多ZF开发,如果我使用基于文件系统的会话,我会将它们粘贴在应用程序/数据/会话中而不是系统默认值。
答案 3 :(得分:1)
最后,答案是废弃会话并编写我自己的非常简单的cookie代码,它与会话有以下不同之处:
这不是一个理想的情况,因为有一些重新发明的轮子,但我的小解决方案似乎适用于PHP会话没有,并有一个工作网站是最重要的事情。
答案 4 :(得分:0)
您的网站位于不同的域名吗?例如domain.com,www.domain.com,subdomain.domain.com?如果某些页面被重定向到不同的域(www被认为是一个不同的子域),那么当地址改变时会话将不起作用
编辑: 您必须重现该问题。询问您的客户他们使用什么类型的浏览器,他们做什么行动,直到他们被抢劫,他们是否正在查看与您相同的网站IP? (即你们都在外部网络中,或者两者都在与网站相同的网络中)
当您设法找到问题时,请检查会话工作时的请求/响应标头,以及它何时不起作用然后进行比较。
答案 5 :(得分:0)
你的session.gc_maxlifetime设置为1440毫秒,仅为1.44秒。不应该是1440000毫秒= 24分钟?
答案 6 :(得分:0)
您可以尝试将session.use_only_cookies
设置为1,将session.cookie_lifetime
设置为1440秒。
答案 7 :(得分:0)
最后,我选择在每个页面请求上发送一个Set-Cookie标头,类似于FlyBy在其中一条评论中建议的内容。现在相关的代码/逻辑是(假设已经调用了session_start()):
$this->session_name = session_name();
$update_cookie = isset($_COOKIE[$this->session_name]); // Check if cookie already set, as PHP will send the first Set-Cookie when the session is started
$this->logged_in = $this->checkSession(); // Function which checks whether a valid (i.e. not timed-out) session row exists in the DB
if ($this->logged_in) {
$this->updateSession(); // Update the session row to the current time
if ($update_cookie) {
// Update the cookie expiry only if it existed before the login check
setcookie($this->session_name, $_COOKIE[$this->session_name], $this->time + 3600, '/');
}
}
我不确定为什么会这样,但我没有任何进一步的抱怨,并且登录次数大幅下降(相同用户的日志中不再有几次登录在几分钟之内)。
但是,我可能会在某些时候重写代码,只是在客户端上使用数据库行和cookie,因为PHP中的会话功能有很多变量,很难找出造成问题的原因,会话cookie处理与正常cookie的处理方式略有不同。特别是,你必须小心setcookie函数,因为PHP启动的会话cookie的默认路径是'/',但setcookie的默认路径是当前目录路径,这些路径不一定相同。