單純依賴 session.gc_maxlifetime 不可靠:GC 是概率觸發(gc_probability/gc_divisor),且無法精確控制單用戶閒置超時。需結合「伺服器端時間戳驗證」實現嚴格管控。
ini_set('session.gc_maxlifetime', 3600); // GC 最大生存 1 小時
ini_set('session.cookie_lifetime', 3600); // Cookie 存活 1 小時(0 為瀏覽器關閉即失效)
缺點:GC 不準時、無法針對單用戶、跨伺服器共享 Session 時需統一存儲。
<?php
session_start();
const IDLE_TIMEOUT = 3600; // 1 小時無操作視為超時
// 1. 檢查是否已登錄且未超時
if (isset($_SESSION['user_id'])) {
$now = time();
if (isset($_SESSION['last_activity']) && ($now - $_SESSION['last_activity'] > IDLE_TIMEOUT)) {
// 超時:銷毀會話並跳轉登錄
session_unset();
session_destroy();
header('Location: login.php?timeout=1');
exit;
}
// 未超時:刷新最後活動時間
$_SESSION['last_activity'] = $now;
}
// 2. 登錄成功時初始化
// $_SESSION['user_id'] = $userId;
// $_SESSION['last_activity'] = time();
// 使用 Redis 存儲 Session,Key 設置 TTL
// Key: session:{session_id} Value: JSON(session_data) Expire: 3600
// 每次請求:
$redis->expire("session:{$sessionId}", 3600); // 滑動過期,續期
// 優點:天然支援集群、TTL 精確到秒、無 GC 隨機性、可直接掃描過期 Key 做統計。
| 配置 | 含義 | 建議值 |
|---|---|---|
session.gc_maxlifetime | GC 視為垃圾的最小秒數 | 3600 |
session.cookie_lifetime | 瀏覽器端 Cookie 存活秒數 | 3600(或 0 會話級) |
session.gc_probability | GC 概率分子 | 1 |
session.gc_divisor | GC 概率分母 | 1000(降低頻率) |
session.save_handler | 存儲驅動 | redis / memcached |
session_start() 並執行超時檢查中間件。last_activity。