首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 面試必考:如何實現「嚴格 30 分鐘過期」的 Session?四種答案遞進解析

     編輯:PHP 相關知識

題目:如何設置一個嚴格 30 分鐘過期的 Session?

看似簡單,實則考察對 Session 機制、GC 隨機性、Cookie 與 Session 差異、分布式存儲的深度理解。

答案一:修改 gc_maxlifetime(❌ 不嚴格)

ini_set('session.gc_maxlifetime', 1800); // 30分鐘

致命缺陷:

  1. GC 是概率觸發:默認 1% 機率,30 分鐘到期不代表立即刪除,可能延遲數小時
  2. 修改時間判斷:GC 以文件 mtime 為準,若用戶 5 分鐘前活躍,文件 mtime 更新,實際存活 35 分鐘
  3. 共享目錄污染:多應用共用 /tmp,最小 gc_maxlifetime 會誤刪其他應用 Session

答案二:設置 cookie_lifetime(❌ 客戶端不可信)

ini_set('session.cookie_lifetime', 1800);

致命缺陷:

  • 僅控制瀏覽器 Cookie 過期,服務端 Session 文件依然存在
  • 攻擊者可攜帶過期 Session ID 繼續訪問(構造請求頭)
  • 不同瀏覽器/客戶端對 Cookie 過期處理不一致

答案三:使用 Redis/Memcached 設置 TTL(✅ 架構級正確)

// Redis 自動過期,精確到毫秒
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379?auth=pass');
// Session 寫入時自動 EXPIRE 1800

優勢:

  • 服務端強制過期,無 GC 隨機性
  • 天然支持分布式、多節點共享
  • 原子操作、高性能

答案四:純 PHP 實現「嚴格 30 分鐘」的工程級方案(✅ 面試加分項)

<?php
// 1. 啟動 Session(放在所有輸出前)
session_start();

// 2. 設置 Cookie 參數(同步客戶端預期)
$lifetime = 1800; // 30分鐘
session_set_cookie_params($lifetime, '/', '', true, true); // Secure + HttpOnly

// 3. 每次請求檢查服務端時間戳
if (isset($_SESSION['_last_activity'])) {
    $idle = time() - $_SESSION['_last_activity'];
    if ($idle > $lifetime) {
        // 嚴格過期:銷毀 Session
        session_unset();
        session_destroy();
        session_start(); // 重新生成新 Session ID
        session_regenerate_id(true);
    }
}

// 4. 更新最後活躍時間
$_SESSION['_last_activity'] = time();

// 5. 可選:定期清理舊 Session 文件(配合 Cron)
// find /var/lib/php/sessions -type f -cmin +30 -delete

方案四核心邏輯圖解

  1. 雙重保險:Cookie 過期引導用戶端清理 + 服務端時間戳強制校驗
  2. 即時生效:每次請求檢查,無 GC 延遲
  3. 防固定攻擊:過期後 session_regenerate_id(true) 刪除舊 Session 文件
  4. 兼容性:無需額外擴展,文件/數據庫/Redis 均可用

面試追問應對

生產環境建議配置

; php.ini 生產建議
session.gc_probability = 0          ; 禁用內建 GC
session.gc_divisor = 100
session.gc_maxlifetime = 1800       ; 兜底值
session.cookie_lifetime = 1800      ; 客戶端提示
session.cookie_httponly = 1         ; 防 XSS
session.cookie_secure = 1           ; 僅 HTTPS
session.cookie_samesite = Strict    ; 防 CSRF
session.use_strict_mode = 1         ; 拒絕未初始化 ID
session.sid_length = 32             ; ID 長度
session.sid_bits_per_character = 5  ; 熵值
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
追問核心回答要點
為什麼不用 gc_maxlifetime?概率觸發、mtime 延遲、共享目錄污染
如何解決分布式 Session 共享?Redis/Memcached + 統一 save_handler
Session 劫持如何防範?HttpOnly、Secure、SameSite、定期 Regenerate ID、綁定 UA/IP 指紋
如何實現「記住我」長期登錄?獨立 Remember Token 表,Token 加密存儲 Cookie,驗證後自動登錄並重置 Session
Session 與 JWT 區別?Session 有狀態/服務端存儲/可撤銷;JWT 無狀態/客戶端攜帶/不可撤銷(除非黑名單)