PHP中的会话超时:最佳实践

时间:2009-08-06 00:09:33

标签: php security cookies session-timeout

session.gc_maxlifetimesession_cache_expire()之间的实际差异是什么?

假设我希望用户会话在非活动15分钟后无效(在首次打开后不是15)。哪一项对我有帮助?

我也知道我可以session_set_cookie_params()这可以设置用户的cookie在一段时间内过期。但是,cookie到期以及服务器端的实际会话到期时间并不相同;这也会在cookie过期时删除会话吗?

我的另一个解决方案很简单 $_SESSION['last_time'] = time() 在每个请求上,并将会话与当前时间进行比较,根据该请求删除会话。我希望有一个更“内置”的机制来处理这个问题。

感谢。

4 个答案:

答案 0 :(得分:53)

我花了一些时间寻找php.ini服务器设置如何制作的好答案 会话到期。我发现了很多信息,但需要一段时间来弄清楚原因 设置按照他们的方式工作。如果你像我一样,这对你有帮助:

会话作为cookie(客户端的PC上的文件)或服务器端存储为文件 在服务器上。这两种方法都有优点和缺点。

对于存储在服务器上的会话,使用了三个变量。

session.gc_probability合 session.gc_divisor 的session.gc_maxlifetime

(session.gc_probability / session.gc_divisor)产生概率 垃圾收集例程将运行。当垃圾收集器运行时,它 检查至少session.gc_maxlifetime尚未访问的会话文件 并删除它们。

这在论坛帖子中都很好解释(特别是这个!) - 但是 以下问题确实出现了:

1。)该概率如何应用?服务器什么时候掷骰子?

答:服务器每次调用session_start()时都会掷骰子 服务器上的任何活动会话。所以这意味着你应该看到垃圾 收集器大约运行一次,每100次调用一次session_start() 如果你有默认的session.gc_probability = 1和session.gc_divisor = 100

2.。)低容量服务器会发生什么?

答:调用session_start()时,FIRST刷新会话并生成 会话值可供您使用。这会更新会话文件的时间 服务器。它然后滚动骰子,如果它赢了(百分之一的机会),它会调用垃圾收集器。垃圾收集器然后检查所有会话ID文件并查看是否存在 任何有资格删除的人。

所以这意味着如果你是服务器上唯一的人,你的会话就会 永远不会失效,看起来好像改变设置没有 影响。假设您将session.gc_maxlifetime更改为10和session.gc_probability 这意味着垃圾收集器有100%的可能性运行它 将清除在过去10秒内未访问过的任何会话文件。

如果您是服务器上唯一的一个,则不会删除您的会话。你需要 至少有一个其他活动会话正在运行,以使您处于非活动状态。

所以基本上,在低容量服务器上或在低音量时间 - 它可能很多 比垃圾收集器实际运行之前的session.gc_maxlifetime更长 会话实际上已删除。并且不知道这是如何工作的,它可能会 对你来说完全随机。

3.)为什么他们使用概率?

A:表现。在较高容量的服务器上,您不需要垃圾收集器 在session_start()的每个请求上运行。它会减慢服务器的速度 不必要的。因此,根据您的服务器数量,您可能希望增加 或者降低垃圾收集器运行的概率。

我希望这能为你们联系起来。如果你像我一样,你试过 session.gc_maxlifetime并没有起作用(因为你试过了 在开发服务器上,以免打扰任何人),然后这篇文章 希望能让你有点头疼。

祝你好运!

答案 1 :(得分:40)

每次调用session_start会话文件时间戳(如果存在)都会更新,用于计算是否已超过session.gc_maxlifetime。

更重要的是,在超过session.gc_maxlifetime时间之后,您不能依赖会话到期。

PHP在加载当前会话后在过期的会话上运行垃圾收集,并使用session.gc_probabilitysession.gc_divisor计算垃圾收集运行的概率。默认情况下,概率为1%。

如果您的访问者数量较少,则非活动用户可能会访问应该已过期并已删除的会话。如果这很重要,则需要在会话中存储时间戳并计算用户的非活动日志。

此示例替换session_start并强制执行超时:

function my_session_start($timeout = 1440) {
    ini_set('session.gc_maxlifetime', $timeout);
    session_start();

    if (isset($_SESSION['timeout_idle']) && $_SESSION['timeout_idle'] < time()) {
        session_destroy();
        session_start();
        session_regenerate_id();
        $_SESSION = array();
    }

    $_SESSION['timeout_idle'] = time() + $timeout;
}

答案 2 :(得分:5)

session.gc_maxlifetime 基于上次修改会话文件的时间。因此,每次修改会话文件或在单独的页面中调用session_start()时,gc_maxlifetime的倒计时将重新开始,用户将保持“登录”状态。这是您正在寻找的价值。你可以通过php文件中的ini_set()修改它,或者如果你有权访问它就编辑php.ini

session_cache_expire()仅控制HTTP“Expires”标头。此标题控制下载的页面内容保留在用户浏览器缓存中的时间。

答案 3 :(得分:1)

要检查当前值,此代码将非常有用:

$gc_maxlifetime = ini_get('session.gc_maxlifetime');
$gc_probability = ini_get('session.gc_probability');
$gc_divisor     = ini_get('session.gc_divisor');