【发布时间】:2018-04-16 14:56:32
【问题描述】:
我正在尝试改进 Web 应用程序的会话管理。我的主要问题是会话到期以及如何处理它。为此,我想知道会话是否仍然可用。我使用的是默认的基于文件的会话(PHP 7.1、Apache 2.4、Fedora/RHEL),它是基于 cookie 的。
我发现当调用session_start() 时会执行会话GC。它与脚本执行的开始或结束无关,它发生在此函数中。我觉得奇怪的是,如果session_start() 和 GC 认为会话已过期并想要删除相应的会话文件,则 $_SESSION 首先会定期填充,然后该文件将被删除。这很令人惊讶。
在这种行为下,只有下一个请求会导致空的 $_SESSION。我希望之前的调用会出现这种情况 - 删除文件的调用。因此,如果我想知道当前请求中的会话是否已过期,我必须检查在session_start() 调用之后会话文件是否仍然存在。这对我来说似乎很奇怪。
除了查看文件系统之外,还有其他更好的方法来检查会话是否已过期?
我想我可以检查 $_SESSION 是否为空来确定会话是否已更新 - 但这显然是不可能的。
更新:我发现了以下处理该问题的错误报告:this 和 that。还有一个关于过期问题的SO entry。当前 PHP 源代码:php_session_start 调用 php_session_initialize 调用 php_session_gc。
您可能想玩这个脚本(虚幻设置仅用于测试目的):
ini_set('session.gc_maxlifetime', 2); // Session gets expired after 2 seconds
ini_set('session.gc_divisor', 1); // Delete expired session files immediately
ini_set('session.save_path', '/some/safe/path/for/testing'); // Must be accessible for the server
//ini_set('session.use_strict_mode', true); // Uncomment if the id should be renewed, what makes no difference here
echo "Session files before session_start call<br>";
listSessionFiles();
session_start();
echo "Session files after session_start call<br>";
listSessionFiles();
echo "<hr>";
echo "Session id: " . session_id() . "<br>";
echo "Session content: " . print_r($_SESSION, true);
$_SESSION['x'] = time(); // Populate the session with something
function listSessionFiles() {
echo "<ul>";
$none = true;
$dir = dir(ini_get('session.save_path'));
while ($entry = $dir->read()) {
if (preg_match('/^sess_/', $entry)) {
echo "<li>" . $entry . "</li>";
$none = false;
}
}
$dir->close();
if ($none) echo "<li>None</li>";
echo "</ul>";
}
只需重新加载页面几次。等待至少两秒钟以上。否则会话不会过期。
【问题讨论】:
-
将 GC 设置为在每个请求上运行是相当荒谬的。 PHP 会话没有实际的过期时间,它们只有最短的生命周期。如果你想要一个 max 生命周期,那么你应该自己实现 - 将最后一次访问时间存储在会话中,并在下一次访问时与当前时间进行比较,然后决定是继续还是终止本次会议。
-
@CBroe 那个脚本只是用来玩的。当然我不使用这些设置。不,我不想要最长的寿命。我只是想知道会话是否已过期。
-
确实像 @CBroe 所说的
Setting the GC to run on every single request is rather nonsense.此外,由于需要磁盘 i/o,它可能会导致延迟。 -
@RaymondNijland 我知道。脚本只是为了尝试。但是,问题不受这些设置的影响。
-
"我发现会话 GC 是在 session_start() 被调用时执行的。它不是脚本执行的开始或结束,它发生在这个函数上.” - 是经过验证的事实(通过检查 PHP 源代码),还是只是一个假设,因为从您所看到的情况来看它“感觉像它”?我认为,2 秒的生命周期也可能会扭曲您的结果/观察结果。除非这是在半现实条件下进行测试,否则我认为这现在根本证明不了任何事情。
标签: php session session-cookies