[英]How can i stop an AJAX call keeping a PHP Session alive
我的站點上有一個使用 CakePHP 的身份驗證系統。 它為此使用 PHP 會話。
What i have in place is an AJAX call (within a setInterval running every minute) to a function which checks if the user is still logged in. If it returns false, then the Javascript takes the current URL and attempts to redirect them, which in turn 將他們重定向到登錄頁面。 從理論上講,這是可行的,因為它主動要求用戶重新登錄,而不是持有陳舊的 session,后者只會要求他們在單擊某些內容時立即登錄。 我的問題是我的 AJAX 調用使 session 保持活動狀態。 所以永遠不要退出(我們不想要)
我可以在 CakePHP 或任何其他我可以用來阻止這種情況發生的方法中做些什么嗎?
當您檢查 session 的有效性時,將&ajax=
(anything) 添加到查詢字符串。
然后,更改您的 PHP session 代碼:
session_start();
if(!isset($_GET["ajax"])) $_SESSION["lastactivity"] = time();
if(now() - $_SESSION["lastactivity"] > 3600){ //3600 seconds
header("Location: login.php?url="+urlencode(str_replace("&ajax=", "", $_SERVER["REQUEST_URI"])));
//Example:
// Location: login.php?url=/sensible/secret.php?mode=show&hide=nothing
exit;
}
這並不能完全回答您提出的問題,但我認為這是我認為我會分享的最佳實踐。
setInterval() 實際上並不像您期望的那樣運行。 這並不意味着您的代碼每分鍾都會執行一次,它只是確保您的代碼每分鍾都會被添加到隊列中。
這樣做的問題是,在代碼再次添加到隊列之前,計時器代碼可能無法完成執行。 結果將是計時器代碼連續運行多次,它們之間沒有時間。 幸運的是,JavaScript 引擎足夠聰明,可以避免這個問題。 使用 setInterval() 時,僅當隊列中沒有計時器代碼的其他實例時,才會將計時器代碼添加到隊列中。 這確保了將計時器代碼添加到隊列之間的時間至少是指定的時間間隔。
重復計時器的這種規定的缺點是雙重的:(1)可能會跳過間隔,以及(2)間隔可能小於多個計時器代碼執行之間的預期...... -N。 Zakas, Web 開發人員的專業 JavaScript
解決這個問題的方法是像這樣格式化你的計時器代碼:
setTimeout( function() {
// code to be run
setTimeout( arguments.callee, *interval* );
}, *interval* );
注意: arguments.callee 不能在嚴格模式下使用。
在這里,我推導出了一個用於檢測 session 是否存在的解決方案。
不需要任何開銷。我們可以在正常的 http 請求上檢測並重定向 session 超時。 就像在 ajax 中一樣,我們應該用一些邏輯來區別對待。
在 php 端。 首先創建一個身份驗證 function 應該必須在所有頁面的第一行調用此身份驗證。
Best to add this auth() function in config.php file or auth.php file and include in all the php file after the session creation.
包括'config/auth.php';
// in auth.php file copy and past the following lines
function auth() {
if (!isset($_SESSION['USER_ID'])) {
// checking whether the request is ajax or not. Ajax requests are xml http request
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
// set a status code manually. 418 is unused http code
header("HTTP/1.0 418 Session Timeout", TRUE);
// return or send a json response with status string and location to redirect
echo json_encode(array(
"status" => "time_out",
"location" => BASE_URL . "login.php?message=Session Timeout! Please log in and Try again.",
));
exit;
}
// whether the request is normal http request do the redirection from the server side
if (basename($_SERVER['PHP_SELF']) != 'login.php') {
header("Location:" . BASE_URL . "login.php");
}
} }
這里我使用 jQuery 創建一個 js 文件,該文件必須在項目中的所有 html( 模板 ) 頁面中調用。
最好包含在commen header 或頁腳中
創建 ajax 設置
$.ajaxSetup({
statusCode: {
418: function (respose) {
// $.parseJSON() can avoid by specifying dataType:"json" in ajax parameters
var jsonObject = $.parseJSON(respose.responseText);
if (jsonObject.status == "time_out") {
window.location = jsonObject.location;
}
}
}
});
祝你有美好的一天...
您描述的 AJAX ping 最常用於此目的 - 保持 session 活着。 您在 session 處於活動狀態時訪問了您的應用程序,這一事實正在刷新它。
您可以執行以下操作之一:
我會選擇第二個選項 go 。
這樣做的明顯方法是:
作為一個丑陋的黑客,你可以嘗試調用 session_id('dummy'); 或在 Ajax 端點中調用 session_start() 后更改 session 處理程序。
正如我在評論中提到的,您可以創建一個包含以下內容的 javascript 文件,並在所有頁面中調用此文件
setTimeout("checkSession()",1800000);
function checkSession(){
//alert("Your session has expired due to inactivity. You will be logged out");
window.location.reload();//or window.location="logoutAction";
}
我認為您不能單獨依靠 Auth session 來實現這一點。
我要做的是在用戶表上創建一個新字段來跟蹤上次活動,例如last_activity
作為 mysql 時間戳。 然后在您的AppController::beforeFilter()
中,將此字段設置為使用當前日期時間進行更新(因此每個請求都會發生),但如果是您發出請求的 ping 操作,則將其設置為跳過此字段(您可以檢查$this->here
或者甚至為其他操作添加您自己的參數)。
您的 Ajax ping 顯然只是讀取此字段,如果超過 x 分鍾前,您將注銷用戶。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.