php $_SESSION 变量随机消失并重新出现

php $_SESSION variables disappear and reappear randomly

Preface: this is a "development" from an earlier question of mine, whose answers didn't solve my problem in the end. But through trying all the suggestions and also trying other stuff, I discovered that the real problem is something else, so I rephrase my question here

我有一个登录 page/system,多年来一直正常工作,让用户一直登录,直到 he/she 关闭浏览器 window 或手动注销。但最近,在闲置几分钟后,会话 cookie/s 似乎过期,导致用户自动注销。

不同的浏览器和不同的操作系统都会出现这种情况,PHP版本是5.6.29,最近改了(之前是5.5甚至5.3)。

我使用 session_start() 在每个页面上创建和刷新会话。登录脚本首先检查用户名和密码,并从数据库中获取一些其他用户数据。这些其他数据和成功登录状态保存在会话变量中,如

$_SESSION['username'] = $name;
$_SESSION['usertype'] = $type;
$_SESSION['login'] = "ok";

在其他页面上,我这样检查登录状态:

session_start();
if(($_SESSION['login'] != "ok") OR ($_SESSION['usertype'] != "xxx")) {
 header("Location: ../login.php"); /* redirects to login page if conditions are not true */
 exit;
 }

登录有效,登录用户可以在一段时间内继续访问其他页面,但一段时间后(变化很大),he/she 似乎注销(即尝试打开另一个页面时重定向到登录页面)。

然后我注意到(在开发人员工具中)会话 ID cookie 在会话似乎已过期后保持相同的值(我曾想过,因为会话变量走了)。但是会话并没有过期,只是会话变量消失了。在我的测试中,我尝试在某些页面上回显其中一些变量,但我偶然发现,在它们已经消失(没有回显输出)之后,当我重新加载几分钟后,它们 重新出现 页面或更改到另一个页面。

这就是我目前陷入困境的地方:这怎么会发生,尤其是:我该怎么做才能防止这些变量玩捉迷藏?

(顺便说一句,我无权访问服务器设置 - 这是在共享网站空间上...)

这不是解决方案,只是对我在评论中写的案例的测试。你能试试这个吗?

<?php

$number = (int)$_GET["number"];
$temp_dir = "/tmp/lbtest123";

if (!is_dir($temp_dir)) {
    if (!mkdir($temp_dir, 0777, true)) {
        die("Can't create directory: $temp_dir");
    }
}

file_put_contents($temp_dir."/".$number.".txt", "");

echo "<pre>\n";
print_r(glob($temp_dir."/*.txt"));
echo "</pre>";

将此复制到您的服务器。 它使用作为参数传递的数字在 /tmp/lbtest123 文件夹中创建文件。然后列出已经创建的文件。

用递增的数字调用它,持续的时间与您期望 "logout" 发生的时间相同。示例:

示例结果:

Array
(
    [0] => /tmp/lbtest123/1.txt
    [1] => /tmp/lbtest123/2.txt
    [2] => /tmp/lbtest123/3.txt
    [3] => /tmp/lbtest123/4.txt
)

我希望它在一段时间后显示如下内容:

Array
(
    [2] => /tmp/lbtest123/4.txt
    [3] => /tmp/lbtest123/5.txt
)

Array
(
    [0] => /tmp/lbtest123/1.txt
    [1] => /tmp/lbtest123/2.txt
    [2] => /tmp/lbtest123/3.txt
    [3] => /tmp/lbtest123/6.txt
)

对于任何感兴趣的人:

显然@Crouching Kitten 是对的 - 提供商的架构在负载均衡器或类似的东西后面有多台机器,对此我无能为力。

所以我接受了他的建议,现在将之前作为会话变量的所有内容(连同会话 ID)保存在我在该网站每个页面开头访问的数据库中。我还在其中保存了一个时间戳,它会随着包含相同会话 ID 的每个新查询进行更新,因此我可以设置一个 cronjob,每半小时清除一次过时的数据(超过 90 分钟 - 但该间隔可以是任何时间)。