4 回答

TA贡献1789条经验 获得超10个赞
您需要向 javascript 传递某种永久 UID,即使在会话过期后也能识别用户。
为了简化起见,我正在使用user_name您的代码中已经存在的那个。但是您也可以为每个用户分配一个 UUID,这样就无法猜测另一个用户的名称,也无法修改他们的统计信息。
首先,您将把$_SESSION['user_name']from PHP 传递给 JS 闭包。
let userName = "<?php echo $_SESSION['user_name']; ?>"; // don't forget to wrap the JS string value in quotes or apostrophes
然后,您将在 AJAX 请求负载中传递它。
data: {
action: 'logout',
user_name: userName // added param
},
最后,您将覆盖发送到 DB 的值(如果它与有效负载一起发送)
$usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : ''; // original line
if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
$usname = $_GET['user_name'];
}
$stmt->bind_param('sss', $open, $write, $usname); // original line
完整更新代码:
<?php
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
session_destroy(); // destroy session data in storage
!isset($_SESSION['pageadmin']);
$open = "false";
$write = "0";
$stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
$usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
if (isset($_GET['user_name']) && !empty($_GET['user_name'])) {
$usname = $_GET['user_name'];
}
$stmt->bind_param('sss', $open, $write, $usname);
$stmt->execute();
}
?>
<script>
jQuery(document).ready(function($) {
let lastActivity = <?php echo time(); ?> ; // storing last activity of user
let now = <?php echo time(); ?> ;
let logoutAfter = 10;
let userName = "<?php echo $_SESSION['user_name']; ?>";
let timer = setInterval(function() {
now++;
let delta = now - lastActivity;
console.log(delta);
if (delta > logoutAfter) {
clearInterval(timer);
//DO AJAX REQUEST TO close.php
$.ajax({
url: "/abc/mno.php",
type: 'GET',
data: {
action: 'logout',
user_name: userName
}, // Line A
success: function(data) {
console.log(data); // Line B
},
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus);
}
});
}
}, 1000);
});
</script>
最后的几点说明:
将 PHP、HTML 和 JS 完全组合在一个文件中是一种不好的做法。
您的代码的某些部分不容易重现,我不得不从上下文中猜测(例如,我猜想会话已经设置,使用了 jQuery 但没有
<script src="...jquery.js">
,有一个 DB 查询但没有单独的 SQL 导入来尝试它迅速地)。请在您的下一个问题中阅读并应用如何创建一个最小的、可重现的示例中的知识,以便更多的人能够或愿意帮助您。

TA贡献1777条经验 获得超10个赞
问题是您没有更改任何会阻止会话在 N 秒后过期的内容,您只是在编写脚本以使其在此时间后销毁会话。会话 gc(垃圾收集器)定期执行并删除旧会话,当这种情况发生时,$_SESSION['LAST_ACTIVITY']
也将被删除。
您必须尝试阻止 gc 删除会话或更改应用程序中的逻辑。

TA贡献1921条经验 获得超9个赞
PHP 进程不会无限期地坐下来,也没有程序结构作为循环 ala Node.js 服务器,它不允许您对会话到期做出反应,因为它不是使其无效的进程,而是与会话相关联的简单时间戳每次您尝试使用它时都会检查它。
我提供的解决方案是一个简单的脚本,它每 N 分钟运行一次,以执行最后一次用户活动时间戳(我假设根据该用户的请求更新)与到期期限(在您的情况下为 30 分钟)的比较。您还可以将会话到期时间设置为 30 分钟,但严格来说这不是必需的。如果时间差将超过 30 分钟,则更新表中用户的时间戳,并在必要时使他们的会话无效。该脚本可以通过 cron 或其替代方案运行,并通过您需要执行检查的所有用户。
不要忘记处理用户在服务器上注销但客户端不知道并可能继续发送注销请求的情况 - 引发警报框相当不清楚(最好返回 HTTP Unauthorized 代码并以不同方式处理 - 重定向例如登录屏幕)

TA贡献1863条经验 获得超2个赞
您需要解决两件事。
1)。将 ajax 请求设置为async:false.
$.ajax({
url: "/abc/mno.php",
type: 'GET',
async: false, // <---- ADDED ASYNC FALSE
data: {
action: 'logout'
}, // Line A
success: function(data) {
console.log(data); // Line B
},
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus);
}
});
2)。执行 SQL 查询后销毁会话。
<?php
session_start();
if (isset($_GET['action']) && $_GET['action'] == "logout")
{
!isset($_SESSION['pageadmin']);
$open = "false";
$write = "0";
$stmt = $connect->prepare("UPDATE trace_users SET open=?, write=? WHERE user_name=?");
$usname = !empty($_SESSION['user_name']) ? $_SESSION['user_name'] : '';
$stmt->bind_param('sss', $open, $write, $usname);
$stmt->execute();
session_destroy(); // destroy session data in storage <---- DESTORY AT THE END
}
?>
添加回答
举报