Session 與 Cookie 是 Web 狀態管理兩大基石。本文從儲存位置、生命週期、安全性、應用場景四個維度深度對比。
核心差異速查表
| 維度 | Session | Cookie |
| 儲存位置 | 伺服器端(檔案、Redis、DB、Memcached) | 客戶端瀏覽器(記憶體/硬碟) |
| 資料大小 | 無實質限制(受伺服器記憶體/儲存限制) | 單 Cookie ≤ 4KB,總數 ≤ 300/域名 |
| 生命週期 | 瀏覽器關閉失效(Session Cookie),或設定 gc_maxlifetime | 可設定 Expires/Max-Age,持久化數月/年 |
| 安全性 | 較高(資料不暴露客戶端,僅傳 Session ID) | 較低(可被竄改、XSS 竊取、CSRF 利用) |
| 頻寬影響 | 每請求僅傳 Session ID(約 32 字元) | 每請求攜帶所有 Cookie 資料 |
| 跨域支援 | 需同域或共享儲存體 | 可設定 Domain/Path 跨子域 |
| 禁用 Cookie 影響 | 需 URL 重寫/隱藏表單傳 SID | 完全失效 |
Session 運作機制
- 用戶首次請求 → 伺服器建立 Session、生成 Session ID
- 伺服器回應 `Set-Cookie: PHPSESSID=abc123; path=/; HttpOnly`
- 瀏覽器儲存 Cookie(記憶體,關閉瀏覽器即失效)
- 後續請求自動攜帶 `Cookie: PHPSESSID=abc123`
- 伺服器讀取 Session ID,載入對應 Session 資料
Session ID 傳遞方式
- **Cookie**(預設、最常用)
- **URL 重寫**:`page.php?PHPSESSID=abc123`(`session.use_trans_sid=1`)
- **隱藏表單**:``
Cookie 運作機制
time() + 30*86400,
'path' => '/',
'domain' => '.example.com', // 共享子域
'secure' => true, // 僅 HTTPS
'httponly' => true, // JS 不可讀(防 XSS)
'samesite' => 'Lax', // CSRF 保護
]);
// 讀取
$token = $_COOKIE['remember_token'] ?? null;
典型應用場景
| 場景 | 推薦方案 | 理由 |
| 用戶登入狀態 | Session + Remember Me Cookie | 安全性高、支援長期記住 |
| 購物車(未登入) | Cookie 或 LocalStorage | 無需伺服器資源、跨 Session 持久 |
| 用戶偏好設定(語言、主題) | Cookie (1 年) | 客戶端可直接讀取、減少請求 |
| CSRF Token | Session 或 Cookie (Double Submit) | 需不可預測、驗證方便 |
| 追蹤用戶行為 (Analytics) | Cookie (第一方/第三方) | 跨 Session 識別唯一訪客 |
| 敏感資料暫存 | Session | 不暴露客戶端 |
安全配置最佳實踐
Session 安全
Cookie 安全
- 敏感 Cookie 必設 `HttpOnly`、`Secure`、`SameSite`
- 定期輪換加密金鑰(若加密 Cookie 內容)
- 實作 Cookie 同意管理(GDPR/個資法合規)
分散式 Session 解決方案
| 方案 | 優點 | 缺點 |
| 檔案系統 (預設) | 零配置 | 不支援多伺服器、效能差 |
| 資料庫 | 持久化、可查詢 | 寫入延遲、連線壓力 |
| Redis (推薦) | 高效能、支援集群、TTL 自動過期 | 需額外基建 |
| Memcached | 極快、簡單 | 無持久化、無備份 |
現代替代:JWT (JSON Web Token)
- 無狀態、可攜帶聲明、跨域友善
- 適用 API、微服務、單頁應用 (SPA)
- 缺點:無法主動撤銷(需黑名單/短期效期)、Payload 可見(勿存敏感資料)