[英]Session timeouts in PHP: best practices
session.gc_maxlifetime
和session_cache_expire()
之間的實際區別是什么?
假設我希望用戶會話在 15 分鍾非活動(而不是首次打開后 15 分鍾)后無效。 其中哪一項會幫助我呢?
我也知道我可以做session_set_cookie_params()
它可以將用戶的 cookie 設置為在一段時間內過期。 但是,cookie 過期和服務器端實際會話過期是不一樣的; 當 cookie 過期時,這是否也會刪除會話?
我想到的另一個解決方案是簡單的$_SESSION['last_time'] = time()
對每個請求,並將會話與當前時間進行比較,然后基於此刪除會話。 我希望有一個更“內置”的機制來處理這個問題。
謝謝。
我花了一些時間尋找 php.ini 服務器設置如何使會話過期的好答案。 我找到了很多信息,但花了一段時間才弄清楚為什么這些設置會按照它們的方式工作。 如果你和我一樣,這可能對你有幫助:
會話存儲為 cookie(客戶端 PC 上的文件)或服務器端存儲為服務器上的文件。 這兩種方法各有優缺點。
對於存儲在服務器上的會話,使用了三個變量。
session.gc_probability session.gc_divisor session.gc_maxlifetime
(session.gc_probability/session.gc_divisor) 產生垃圾收集例程運行的概率。 當垃圾收集器運行時,它會檢查至少在 session.gc_maxlifetime 內未被訪問的會話文件並刪除它們。
這在論壇帖子中都得到了很好的解釋(尤其是這個!) - 但確實出現了以下問題:
1.) 這個概率是如何應用的? 服務器什么時候擲骰子?
答:在服務器上的任何活動會話期間,每次調用 session_start() 時,服務器都會擲骰子。 所以這意味着如果你有 session.gc_probability = 1 和 session.gc_divisor = 100 的默認值,你應該看到垃圾收集器大約每 100 次調用 session_start() 運行一次
2.) 在低容量服務器上會發生什么?
答:當 session_start() 被調用時,它首先刷新會話並使會話值對您可用。 這會更新服務器上會話文件的時間。 它然后擲骰子,如果它贏了(100 次機會中的 1 次),它會調用垃圾收集器。 垃圾收集器然后檢查所有會話 id 文件並查看是否有任何可以刪除的文件。
因此,這意味着如果您是服務器上唯一的人,您的會話將永遠不會處於非活動狀態,並且看起來好像更改設置沒有任何效果。 假設您將 session.gc_maxlifetime 更改為 10,將 session.gc_probability 更改為 100。這意味着垃圾收集器有 100% 的機會運行,並且會清除過去 10 秒內未訪問的所有會話文件。
如果您是服務器上唯一的一個,您的會話將不會被刪除。 您至少需要運行 1 個其他活動會話才能使您的會話處於非活動狀態。
所以基本上,在低容量服務器或低容量時間 - 在垃圾收集器實際運行和會話實際刪除之前,它可能比 session.gc_maxlifetime 長得多。 在不知道它是如何工作的情況下,它對您來說可能完全是隨機的。
3.) 為什么他們使用概率?
一場表演。 在更高容量的服務器上,您不希望垃圾收集器在 session_start() 的每個請求上運行。 它會不必要地減慢服務器的速度。 因此,根據您的服務器容量,您可能希望增加或減少垃圾收集器運行的概率。
我希望這能為你把事情聯系在一起。 如果您像我一樣嘗試了 session.gc_maxlifetime 並且它似乎不起作用(因為您在開發服務器上嘗試了它以免打擾任何人),那么這篇文章希望能讓您免於頭疼。
祝你好運!
每次調用session_start 時,會話文件時間戳(如果存在)都會更新,用於計算 session.gc_maxlifetime 是否已超過。
更重要的是,在超過 session.gc_maxlifetime 時間后,您不能依賴會話過期。
PHP 在加載當前會話后對過期會話運行垃圾收集,並通過使用session.gc_probability和session.gc_divisor計算垃圾收集運行的概率。 默認情況下,它的概率為 1%。
如果您的訪問者數量較少,則不活動的用戶可能會訪問本應已過期並被刪除的會話。 如果這對您很重要,您將需要在會話中存儲時間戳並計算用戶不活動的日志。
此示例替換session_start並強制執行超時:
function my_session_start($timeout = 1440) {
ini_set('session.gc_maxlifetime', $timeout);
session_start();
if (isset($_SESSION['timeout_idle']) && $_SESSION['timeout_idle'] < time()) {
session_destroy();
session_start();
session_regenerate_id();
$_SESSION = array();
}
$_SESSION['timeout_idle'] = time() + $timeout;
}
session.gc_maxlifetime基於上次修改會話文件的時間。 因此,每次修改會話文件或在單獨的頁面中調用 session_start() 時,gc_maxlifetime 的倒計時都會重新開始並且用戶保持“登錄”狀態。 這就是您正在尋找的價值。 您可以通過 php 文件中的 ini_set() 修改它,或者如果您有權訪問它,則編輯 php.ini
session_cache_expire()僅控制 HTTP “Expires”標頭。 此標頭控制下載的頁面內容在用戶瀏覽器緩存中停留的時間。
要檢查當前值,此代碼將很有幫助:
$gc_maxlifetime = ini_get('session.gc_maxlifetime');
$gc_probability = ini_get('session.gc_probability');
$gc_divisor = ini_get('session.gc_divisor');
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.