高流量網站的用戶登入態驗證,核心在於「狀態儲存在哪裡」與「如何快速驗證」。本文從儲存位置、安全性、分散式擴展、生存週期、驗證開銷五個維度對比 Cookie 與 Session,並給出混合方案建議。
| 維度 | Cookie | Session |
|---|---|---|
| 儲存位置 | 客戶端(瀏覽器) | 伺服器端(檔案/Redis/Memcached/DB) |
| 安全性 | 可被竄改、攔截(需簽名/加密) | 本質安全,客戶端僅存 Session ID |
| 分散式擴展 | 天然無狀態,無需同步 | 需共享儲存(Redis/DB)或 Sticky Session |
| 生存週期控制 | 靈活(設定 Expires/Max-Age) | 受限於 gc_maxlifetime、儲存體 TTL |
| 驗證開銷 | 若無簽名需查 DB 驗證;有簽名可無狀態驗證 | 需讀取 Session 儲存體(通常一次網路呼叫) |
| 大小限制 | 單 Cookie ≤ 4KB,總數限制 | 理論無上限(視儲存體) |
多台 Web 伺服器時,Session 預設存本地檔案會導致用戶請求落在不同機器上丟失登入態。解決方案:
將用戶 ID、角色、過期時間等資料序列化,配合 HMAC-SHA256 簽名(或 JWT),存入 Cookie。驗證時只需檢查簽名與過期時間,**完全不查資料庫/Redis**,極大降低延遲與後端壓力。Discuz! 等論壇即採用類似機制。
// 簡易簽名 Cookie 產生
$data = ['uid' => 123, 'role' => 'admin', 'exp' => time() + 86400];
$payload = base64_encode(json_encode($data));
$sig = hash_hmac('sha256', $payload, $secretKey);
$cookieValue = $payload . '.' . $sig;
setcookie('auth', $cookieValue, $data['exp'], '/', '', true, true); // Secure, HttpOnly
| 場景 | 推薦策略 |
|---|---|
| 中小型單體應用 | Session (檔案/Redis) + HttpOnly Cookie 存 Session ID |
| 高併發、微服務、跨域 | JWT (Access Token + Refresh Token) 存 HttpOnly Cookie 或 LocalStorage |
| 極致效能、靜態內容多 | 簽名 Cookie (含用戶資訊) + 短期 Access Token,邊緣節點可直接驗證 |
| 高安全要求(銀行、支付) | Session + 雙因子驗證 + 短 TTL + 裝置指紋綁定 |
HttpOnly、Secure、SameSite 屬性與傳輸加密(HTTPS)。session.gc_probability),高流量下可能延遲清理。Redis 可設定精確 TTL。沒有銀彈,只有權衡。單體應用用 Session + Redis 最省心;微服務/高併發轉向 JWT/簽名 Cookie 降低狀態耦合;安全敏感場景疊加多層防護。理解各自權衡,才能為架構做正確選型。