4 回答

TA貢獻1789條經(jīng)驗 獲得超10個贊
您需要向 javascript 傳遞某種永久 UID,即使在會話過期后也能識別用戶。
為了簡化起見,我正在使用user_name您的代碼中已經(jīng)存在的那個。但是您也可以為每個用戶分配一個 UUID,這樣就無法猜測另一個用戶的名稱,也無法修改他們的統(tǒng)計信息。
首先,您將把$_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
},
最后,您將覆蓋發(fā)送到 DB 的值(如果它與有效負載一起發(fā)送)
$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 完全組合在一個文件中是一種不好的做法。
您的代碼的某些部分不容易重現(xiàn),我不得不從上下文中猜測(例如,我猜想會話已經(jīng)設(shè)置,使用了 jQuery 但沒有
<script src="...jquery.js">
,有一個 DB 查詢但沒有單獨的 SQL 導入來嘗試它迅速地)。請在您的下一個問題中閱讀并應(yīng)用如何創(chuàng)建一個最小的、可重現(xiàn)的示例中的知識,以便更多的人能夠或愿意幫助您。

TA貢獻1777條經(jīng)驗 獲得超10個贊
問題是您沒有更改任何會阻止會話在 N 秒后過期的內(nèi)容,您只是在編寫腳本以使其在此時間后銷毀會話。會話 gc(垃圾收集器)定期執(zhí)行并刪除舊會話,當這種情況發(fā)生時,$_SESSION['LAST_ACTIVITY']
也將被刪除。
您必須嘗試阻止 gc 刪除會話或更改應(yīng)用程序中的邏輯。

TA貢獻1921條經(jīng)驗 獲得超9個贊
PHP 進程不會無限期地坐下來,也沒有程序結(jié)構(gòu)作為循環(huán) ala Node.js 服務(wù)器,它不允許您對會話到期做出反應(yīng),因為它不是使其無效的進程,而是與會話相關(guān)聯(lián)的簡單時間戳每次您嘗試使用它時都會檢查它。
我提供的解決方案是一個簡單的腳本,它每 N 分鐘運行一次,以執(zhí)行最后一次用戶活動時間戳(我假設(shè)根據(jù)該用戶的請求更新)與到期期限(在您的情況下為 30 分鐘)的比較。您還可以將會話到期時間設(shè)置為 30 分鐘,但嚴格來說這不是必需的。如果時間差將超過 30 分鐘,則更新表中用戶的時間戳,并在必要時使他們的會話無效。該腳本可以通過 cron 或其替代方案運行,并通過您需要執(zhí)行檢查的所有用戶。
不要忘記處理用戶在服務(wù)器上注銷但客戶端不知道并可能繼續(xù)發(fā)送注銷請求的情況 - 引發(fā)警報框相當不清楚(最好返回 HTTP Unauthorized 代碼并以不同方式處理 - 重定向例如登錄屏幕)

TA貢獻1863條經(jīng)驗 獲得超2個贊
您需要解決兩件事。
1)。將 ajax 請求設(shè)置為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)。執(zhí)行 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
}
?>
添加回答
舉報