核心差異總覽
| 維度 | Cookie | Session |
| 儲存位置 | 客戶端(瀏覽器) | 伺服器端(檔案/Redis/DB) |
| 容量限制 | 單個 4KB,域名總計 ~300 個 | 理論無上限(受記憶體/磁碟限制) |
| 資料型別 | 僅字串(需自行序列化) | 任意型別(陣列、物件、資源) |
| 生命週期 | 可設定過期時間,持久化可跨會話 | 預設瀏覽器關閉失效,可延長但不宜過久 |
| 安全性 | 可被竄改、竊取(XSS)、CSRF 攜帶 | 資料不外露,僅傳遞 Session ID |
| 跨域支援 | 支援 Domain=.example.com 跨子域 | 不跨域(需共享儲存體+同域 Cookie) |
| 伺服器壓力 | 無(客戶端儲存) | 高併發下 Session 檔案/記憶體壓力大 |
| 瀏覽器支援 | 需啟用 Cookie 功能 | 需 Cookie 或 URL Rewrite 傳遞 SID |
Cookie 機制深度解析
屬性結構
setcookie('name', 'value', [
'expires' => time() + 86400*30, // 30 天
'path' => '/', // 整站有效
'domain' => '.example.com', // 含所有子域
'secure' => true, // 僅 HTTPS 傳輸
'httponly' => true, // JS 無法讀取(防 XSS)
'samesite' => 'Lax', // CSRF 防護:Lax/Strict/None
]);
SameSite 策略選擇
- Strict:完全禁止跨站攜帶(最安全,但外部連結進站會登出)
- Lax:允許 GET 導航攜帶(推薦預設,平衡體驗與安全)
- None:跨站皆攜帶(需
Secure,適用第三方嵌入、SSO)
Session 機制深度解析
流程圖解
- 用戶首次請求 → PHP 生成隨機
session_id(預設 26 字元)
- 透過
Set-Cookie: PHPSESSID=abc123 送至瀏覽器
- 後續請求瀏覽器自動攜帶
Cookie: PHPSESSID=abc123
- PHP 讀取
session.save_path/sess_abc123 反序列化載入 $_SESSION
- 腳本結束自動序列化寫回儲存體
儲存驅動選擇
| 驅動 | 適用場景 | 優點 | 缺點 |
| files (預設) | 單機、低併發 | 零配置 | 多機需共享掛載、inode 消耗大 |
| redis | 分散式、高併發、需 TTL 自動清理 | 效能極佳、原子操作、集群支援 | 需額外元件、序列化開銷 |
| database | 需持久化、稽核、關聯查詢 | ACID、可 SQL 分析 | 寫入延遲、連線池壓力 |
| memcached | 純快取、可接受資料遺失 | 極速 | 無持久化、無 TTL 掃描 |
安全加固清單
ini_set('session.use_strict_mode', 1); // 拒絕未初始化 SID
ini_set('session.cookie_httponly', 1); // 防 XSS 竊取
ini_set('session.cookie_secure', 1); // 僅 HTTPS(生產必開)
ini_set('session.use_only_cookies', 1); // 禁用 URL 透傳 SID
ini_set('session.sid_length', 48); // 加長 SID 抗暴力
ini_set('session.sid_bits_per_character', 6); // 更大熵值
// 定期輪換 SID
if (!isset($_SESSION['initiated'])) {
session_regenerate_id(true);
$_SESSION['initiated'] = true;
}
實戰決策指南
場景 A:記住登入狀態(跨會話)
→ Cookie 儲存加密 Token(JWT 或隨機字串),expires=+30天,HttpOnly+Secure+SameSite=Lax。伺服器端 Redis 驗證 Token 對應用戶 ID。
場景 B:購物車、表單多步驟暫存
→ Session(Redis),資料結構化、可存陣列物件、用戶關閉瀏覽器自動清理。
場景 C:高併發 API 無狀態認證
→ JWT 放 Authorization Header,完全無 Session、無 Cookie,水平擴展零共享狀態。
場景 D:跨子域單點登入 (SSO)
→ Cookie Domain=.parent.com + 共享 Redis Session。登入寫 Session,所有子域讀取同一 Session ID。
常見誤區澄清
- 「Session 比 Cookie 安全」:Session ID 仍靠 Cookie 傳遞,若 Cookie 被竊取同樣被劫持。關鍵在
HttpOnly、Secure、SameSite、短 TTL、定期輪換。
- 「Session 可存無限資料」:預設檔案驅動下,大量 Session 會耗盡 inode/磁碟,務必設
session.gc_maxlifetime、session.gc_probability 並監控檔案數。
- 「關閉瀏覽器 Session 就刪了」:只刪除 Cookie,伺服器端檔案仍存在直到 GC 清理。敏感操作需主動
session_destroy()。
結語
Cookie 與 Session 並非對立,而是互補:Cookie 傳遞身份標識,Session 承載業務狀態。現代架構趨勢:無狀態 JWT + 短期 Redis Session,兼顧擴展性、安全性與開發體驗。根據業務場景選擇儲存策略,並嚴格落實安全屬性配置,才是正解。
- 上一篇文章: PHP Imagick 實作多圖拼接縮略圖:1-4 張智能佈局(單張/左右/三欄/田字格)
- 下一篇文章: PHP strtotime 時間字串解析大全:相對時間、自然語言、格式化輸出與避坑指南
Copyright ©
程式碼之家 All Rights Reserved