我正在尝试改进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>";
}
只需重新加载页面一次。等待至少两秒钟以上。否则会话不会过期。
答案 0 :(得分:0)
解决问题的一种方法是使用具有特定生命周期的cookie(低于会话生命周期)。如果cookie过期,它将无法发送到服务器。然后PHP将在调用session_start()
时创建一个新会话,因此$ _SESSION将为空。
这可能足以发现会话不可用。虽然在PHP中无法区分会话是否已过期或出现任何问题。您可以告诉我没有可用的会话数据,然后做适当的事情(除此之外还会破坏新创建的空会话)。