2010-09-03 101 views
3

關於PHP中Session過期的問題。PHP會話到期

我需要我的服務器扔掉會話的信息,如果用戶已經停用一段時間(用於測試,5秒)。

我已經看過this question,特別是在Gumbo(+28票)的答案,我一直在想這個答案對於非活躍用戶的可​​行性。在我的網站上,我已經實施了這個建議,並且它工作正常,只要用戶在會話過期後至少請求一次數據。但不活躍用戶的問題是他們不要求新的數據。所以過期代碼永遠不會被調用。

我一直期待在我的php.ini session.gc_maxlife和相關參數,但我不能做這樣的工作,我想它的方式。

對此問題的任何建議?

+0

如果您不希望在下一個請求中銷燬過期的會話,您希望發生什麼? – Gumbo 2010-09-03 14:34:13

+1

我沒有看到這裏的問題,除非你依賴過期代碼做一些額外的清理。如果是這種情況,那麼也許一個cron腳本將是一個更好的選擇? – 2010-09-03 14:37:24

+0

我確實希望它被銷燬,但不希望依賴用戶在會話實際銷燬之前發出另一個請求。 – Timo 2010-09-03 14:39:14

回答

1

如果您需要調用特定的到期邏輯(例如,爲了更新數據庫),並希望從獨立的請求那麼它將使意義實現了外部的會話處理器守護進程,着眼於會話文件的訪問時間。 daemon script應執行任何必需的每個會話文件,在指定的時間內未被訪問。

這個解決方案有兩個先決條件:服務器的文件系統支持的訪問時間(Windows沒有),你可以從session save path讀取文件。

+0

只是爲了成爲一個學者,Windows [確實使用訪問時間](http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724290(v = vs.85).aspx) - 並已完成自從開始以來 - 儘管由於性能方面的原因,它在最近的版本中已被[默認禁用](http://superuser.com/a/251265/11305)。 FAT系統只允許1天的分辨率!但NTFS更精確。它仍然不是一個理想的配置,因爲NTFS可以延遲存儲新的時間戳,直到寫入不會影響磁盤性能(最差情況,長達一個小時)。 – Basic 2014-05-31 22:55:46

1

垃圾收集器不是會話調用時,垃圾收集器有一個變化基於TGE gc_ *值被調用,它可以作廢多個會話。所以只要有人觸發它,其他人就可以註銷。如果你需要一個更可靠的方法,如果你的超時時間在幾分鐘內,使用一個cronjob,如果你的超時時間在幾秒鐘內,你將不得不使用某種守護進程。

3

session expiration logic I mentioned確實已經在做你期待什麼:一旦它已過期,不能使用的會話。

會話數據仍在存儲中並不重要,因爲它在到期後不能使用;它將在垃圾收集器下次運行時被刪除。在session_start撥打電話(另請參閱How long will my session last?)之後,session.gc_probability的概率除以session.gc_divisor


編輯既然你想在一個過期的會話執行一些其他任務,我寧願建議使用custom session save handler

當使用的會話保存處理的一類,你可以寫兩個類,一個用於基礎存儲處理器和一個與執行額外的任務延長垃圾收集器,如:

interface SessionSaveHandler { 
    public function open(); 
    public function close(); 
    public function read($id) 
    public function write($id, $data); 
    public function destroy($id); 
    public function gc($callback=null); 
} 
class SessionSaveHandler_WithAdditionalTasks implements SessionSaveHandler { 
    // … 
    public function gc($callback=null) { 
     if (!is_null($callback) && (!is_array($callback) || !is_callable($callback))) return false; 
     while (/* … */) { 
      if ($callback) $callback[0]::$callback[1]($id); 
      // destroy expired sessions 
      // … 
     } 
    } 
    public static function doAdditionalTasksOn($id) { 
     // additional tasks with $id 
    } 
} 
session_set_save_handler(array('SessionSaveHandler_DB_WithAdditionalTasks', 'open'), 
         array('SessionSaveHandler_DB_WithAdditionalTasks', 'close'), 
         array('SessionSaveHandler_DB_WithAdditionalTasks', 'read'), 
         array('SessionSaveHandler_DB_WithAdditionalTasks', 'write'), 
         array('SessionSaveHandler_DB_WithAdditionalTasks', 'destroy'), 
         array('SessionSaveHandler_DB_WithAdditionalTasks', 'gc') 
         ); 
1

的一種方式你可以這樣做,就是使用javascript在超時時間後稍微刷新頁面。授予您的用戶必須啓用Javascript才能使其工作。您還可以添加額外的功能,例如讓javascript彈出超時通知以及倒計時等等。所以必不可少的會話過期由於您的設置,然後刷新命中,清理運行和完成。

<html> 
<head> 
<script type="text/JavaScript"> 
<!-- 
function timedRefresh(timeoutPeriod) { 
    setTimeout("location.reload(true);",timeoutPeriod); 
} 
// --> 
</script> 
</head> 
<body onload="JavaScript:timedRefresh(5000);"> 
</body> 
</html> 
+0

是的,使用心跳是一種選擇,但在您的示例中,「onUnload」事件需要再見功能。即使如此,如果useragent簡單地刪除連接,則不能保證到期事件。但從接受的答案來看,Timo並沒有尋找一種防彈的方式來在會話過期時在服務器上執行自定義代碼。我認爲他只是擔心會話破壞。 – Saul 2010-09-05 14:42:50