会话不能长时间保持自动销毁

时间:2015-10-12 15:17:50

标签: php session

我遇到了会话问题,我的会话在几分钟不活动后自动销毁,我认为它必须是24分钟,即1440秒。我想会话保持很长时间,我正在使用.user.ini文件在服务器上并将 session.gc_maxlifetime 设置为31557600秒,将 session.cookie_lifetime 设置为31557600但是没有任何事情发生在我身上。它仍然在1440秒不活动后退出。我还附上了phpinfo的png图像的会话值。 我希望你的回答或任何帮助对我有用。谢谢。enter image description here

3 个答案:

答案 0 :(得分:1)

如上所述here

  

最佳解决方案是实现您自己的会话超时。用一个   简单的时间戳,表示最后一次活动的时间(即   请求)并随每个请求更新它:

if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
    // last request was more than 30 minutes ago
    session_unset();     // unset $_SESSION variable for the run-time 
    session_destroy();   // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
     

每次请求更新会话数据也会更改会话   文件的修改日期,以便会话不被删除   垃圾收集器过早。

答案 1 :(得分:1)

根据我的经验,它始终与php.ini文件相关。在您的情况下,session.gc_maxlifetime的主值和本地值相矛盾。 (gc代表垃圾收集)他们不必彼此同意,因为本地值用于运行脚本。它只意味着系统上有两个php.ini文件,位于不同的地方,本地php.ini文件覆盖了主php.ini文件设置。但是,我非常怀疑服务器上调用session_start()使用master php.ini文件的任何文件,或者在脚本本身内调用ini_set(...) 。它的工作方式是,无论设置的值是什么,它只有在有时间进行垃圾收集时才有意义。垃圾收集由session_start()完成,但您也可以通过其他方式触发垃圾收集,例如SessionHandler::gc或cronjob,如本文后面所述。调用时,它会检查存储会话信息的服务器上文件的上次修改时间。如果此后经过的秒数大于当前session.gc_maxlifetime值,则会破坏会话。请注意,这是上次修改时间,而不是上次访问的时间,因此您需要经常更改会话数据,以防止在未更改时将其删除。您还应该知道这里有一个名为session.lazy_write的设置,如果已启用,默认情况下已启用,将不会更新事件中会话文件的上次修改时间会话数据没有改变。因此,如果您希望尽量减少会话因某种未知原因而被提前销毁的可能性,或者在会话中存储时间戳以便数据始终发生变化并且您知道上次使用会话时,您将要禁用此功能。如果旧,您可以手动拨打session_destroy()。要开始其他会话,您可以使用session_write_close()进行提交,然后重新调用session_start()。或者,使用session_regenerate_id(true)同时执行所有3。

接下来,如果您使用预期设置初始化session_start()会话,并继续使用每个请求的预期设置调用session_start(),那就太棒了。但是,一旦服务器上的任何文件使用session_start()的不同值调用session.gc_maxlifetime,或者使用您的案例中的主php.ini值,或者调用ini_set(...)的脚本并忽略主值,它将根据不同的值检查文件的最后修改时间并破坏您的会话,尽管您的预期设置 - 假设它被选为100个请求中的1个之一,必须进行垃圾收集。

另一件值得关注的事情是session.cookie_lifetime。值为0会将cookie转换为浏览器会话cookie。这意味着如果用户关闭其浏览器,则会话cookie将被浏览器删除。您的主值使用0.但您的本地值使用31557600(一年中的平均秒数)。所以你应该没事。但是,如果服务器上的任何脚本覆盖此值,请使用值0或使用主php.ini文件,睁大眼睛。

您还应该知道默认的1%垃圾收集 CHANCE ,会话将按照session.gc_probabilitysession.gc_divisor的定义销毁,默认分别为1和100 。当start_session()被调用时,当且仅当请求随机地"}时,才进行垃圾收集。被选为管理垃圾收集的请求。这意味着即使会话的已定义秒数已过期,start_session() STILL 也会赢得垃圾收集,即使此过期会话也是如此。相反,由于浏览器跟踪其时间戳到期的cookie,大多数用户会注意到他们的会话完全按计划到期。但是,在调用start_session()时,根据垃圾收集更改收集PHP垃圾之前,会话不会被强制执行。如果您希望会话在过期时被清除干净并开始新会话,则应使用session_regenerate_id(true)。这里的true表示删除与上一个会话相关联的$_SESSION数据,并将它们的会话ID丢失,就像会话过期一样。

您还应该知道某些系统(例如基于debian的系统)有一个cronjob,每30分钟运行一次,基于主php.ini配置信息进行垃圾收集。 请参阅Christopher Kramer的评论:http://php.net/manual/en/session.configuration.php 我无法验证关于debian系统的上述信息是否属实,但我之前用cronjob考虑过garbage collecting以加快用户的速度'请求所以没有一个用户因为cronjob可能正在处理的维护而不得不等待他们的请求通过。

就解决方案而言:
这里的一个解决方案是调整master php.ini值,如果你有权访问它,那么在服务器上搜索可能正在调用ini_set的任何PHP文件,看看是否有任何文件与你的文件冲突设置以确保它们不会导致意外行为。

另一种解决方案是限制脚本可能遇到的此类冲突:(1。)session.name重命名为PHPSESSID以外的其他内容。和/或(2。)更改session.save_path路径。这些中的任何一个本身都足以避免脚本冲突。

临时修复可能是做一些事情,比如将session.gc_probability更改为0,以便收集会话垃圾。或者通过使用session.gc_probability = 1和session.gc_divisor = 100000这样的机会来减少它的机会。然后设置一个cronjob来调用SessionHandler::gc

有关更多会话配置信息,请参阅http://php.net/manual/en/session.configuration.php

最后,我想向您指出这篇文章,其中提出了防止会话劫持的良好做法,并且大部分内容是我将这篇文章放在一起时引用的帖子:https://stackoverflow.com/a/1270960/466314 请注意,它使用会话方法,确保会话按时到期,而不是以后(尽管浏览器已经通过cookie垃圾收集很好地完成了这项工作)。它还会对会话进行更改,跟踪会话上次使用的时间,因此会话数据始终会发生变化,以避免session.lazy_write出现问题。

我的建议到此结束。如果您可以缩小问题范围,请尝试搜索stackoverflow或提出新问题。

答案 2 :(得分:0)

我不确定为什么您的设置不起作用,但我在脚本上使用以下内容覆盖php.inisession maxlifetime的{​​{1}}设置:

session_save_path

注意:
session_save_path('/pathto/writable/dir/on/your/account'); ini_set('session.gc_maxlifetime', 24*60*60); // 24 hours; change as necessary session_start(); 很重要,因为默认session_save_pathpath,系统管理员可能会每天/每周删除它?基础。