如何設定一個嚴格30分鐘過期的Session

葡萄酒不吐葡萄皮發表於2019-02-16

第一種回答

那麼, 最常見的一種回答是: 設定Session的過期時間, 也就是session.gc_maxlifetime, 這種回答是不正確的, 原因如下:

  1. 首先, 這個PHP是用一定的概率來執行session的gc的, 也就是session.gc_probability和session.gc_divisor(介紹參看 深入理解PHP原理之Session Gc的一個小概率Notice), 這個預設的值分別是1和100, 也就是有1%的機會, PHP會在一個Session啟動時, 執行Session gc. 不能保證到30分鐘的時候一定會過期.

  2. 那設定一個大概率的清理機會呢? 還是不妥, 為什麼? 因為PHP使用stat Session檔案的修改時間來判斷是否過期, 如果增大這個概率一來會降低效能, 二來, PHP使用”一個”檔案來儲存和一個會話相關的Session變數, 假設我5分鐘前設定了一個a=1的Session變數, 5分鐘後又設定了一個b=2的Seesion變數, 那麼這個Session檔案的修改時間為新增b時刻的時間, 那麼a就不能在30分鐘的時候, 被清理了. 另外還有下面第三個原因.

  3. PHP預設的(Linux為例), 是使用/tmp 作為Session的預設儲存目錄, 並且手冊中也有如下的描述:

    Note: 如果不同的指令碼具有不同的 session.gc_maxlifetime 數值但是共享了同一個地方儲存會話資料,則具有最小數值的指令碼會清理資料。此情況下,與 session.save_path 一起使用本指令。 
    

也就是說, 如果有倆個應用都沒有指定自己獨立的save_path, 一個設定了過期時間為2分鐘(假設為A), 一個設定為30分鐘(假設為B), 那麼每次當A的Session gc執行的時候, 就會同時刪除屬於應用B的Session files.

所以, 第一種答案是不”完全嚴格”正確的.
第二種答案

還有一種常見的答案是: 設定Session ID的載體, Cookie的過期時間, 也就是session.cookie_lifetime. 這種回答也是不正確的, 原因如下:

這個過期只是Cookie過期, 換個說法這點就考察Cookie和Session的區別, Session過期是伺服器過期, 而Cookie過期是客戶端(瀏覽器)來保證的, 即使你設定了Cookie過期, 這個只能保證標準瀏覽器到期的時候, 不會傳送這個Cookie(包含著Session ID), 而如果通過構造請求, 還是可以使用這個Session ID的值.
第三種答案

使用memcache, redis等, okey, 這種答案是一種正確答案. 不過, 很顯然出題者肯定還會接著問你, 如果只是使用PHP呢?
第四種答案

當然, 面試不是為了難道你, 而是為了考察思考的周密性. 在這個過程中我會提示出這些陷阱, 所以一般來說, 符合題意的做法是:

  1. 設定Cookie過期時間30分鐘, 並設定Session的lifetime也為30分鐘.

  2. 自己為每一個Session值增加Time stamp.

  3. 每次訪問之前, 判斷時間戳.

相關文章