Cookie 是 HTTP 無狀態特性下維持會話狀態的關鍵機制。雖然現代開發常使用 JWT、Session + Redis 等方案,但 Cookie 仍是瀏覽器端狀態管理的基石。本文系統整理 Java Servlet 中 Cookie 的建立、讀取、刪除操作,並深入剖析 Path (路徑) 屬性對 Cookie 可見性與生命週期的影響,這是許多開發者容易踩坑的地方。
// 建立 Cookie,指定鍵值
Cookie cookie = new Cookie("userToken", "abc123xyz");
// 設定存活時間 (單位:秒)
// 正數:持久化到硬碟,過期自動刪除
// 負數 (預設):會話級 Cookie,瀏覽器關閉即失效,僅存在記憶體
// 0:立即刪除該 Cookie (配合刪除操作使用)
cookie.setMaxAge(60 * 60 * 24); // 1 天有效
// 設定生效路徑 (關鍵!預設為當前 Servlet 映射路徑)
// 瀏覽器只會在請求路徑符合此前綴時攜帶該 Cookie
cookie.setPath("/app/api");
// 設定域 (可選,預設為當前域,支援子域共享)
cookie.setDomain(".example.com");
// 設定安全屬性 (HTTPS 環境下必開)
cookie.setSecure(true); // 僅 HTTPS 傳輸
cookie.setHttpOnly(true); // 防止 XSS 攻擊,JS 無法讀取
// 寫入回應
response.addCookie(cookie);
// 獲取當前請求攜帶的所有 Cookie (陣列,非 Map)
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("userToken".equals(cookie.getName())) {
String value = cookie.getValue();
// 業務邏輯處理...
break;
}
}
}
// 注意:無法直接透過名稱獲取,需遍歷;且無法獲取屬性 (Path、Domain、MaxAge 等),只能拿到 name/value。
核心原則:刪除 Cookie 實質是建立一個同名、MaxAge=0、Path/Domain 完全一致的 Cookie 覆蓋它。
Cookie cookie = new Cookie("userToken", null); // 值設為 null 或空字串
cookie.setMaxAge(0); // 立即失效
cookie.setPath("/app/api"); // **必須與建立時完全一致!**
cookie.setDomain(".example.com"); // 若建立時設定了 Domain,刪除時也必須帶上
response.addCookie(cookie);
Cookie 的 `Path` 屬性決定了瀏覽器在發送請求時是否攜帶該 Cookie。許多「刪除無效」、「跨模組共享失敗」的問題根源皆在於對 Path 機制理解不透徹。
當嘗試刪除一個「當前路徑不存在、但父路徑存在」的同名 Cookie 時,不同瀏覽器表現不一:
| 場景 | Firefox (FF) | Internet Explorer (IE) |
|---|---|---|
| 鍵名全小寫 (如 `key`) | 若當前路徑無,向上遞歸查找父路徑並刪除最近的一個 | 向上查找父路徑 (但會跳過某些層級,行為較不可預期) |
| 鍵名含大寫/混合 (如 `Key`、`USER_ID`) | 同小寫,向上查找 | 不向上查找,僅嘗試刪除當前路徑,找不到則放棄 |
最佳實踐: 建立、讀取、刪除 Cookie 時,永遠顯式指定 `setPath("/")` 或固定的應用根路徑 (如 `/app`),且鍵名統一使用小寫。避免依賴瀏覽器的向上查找行為,消除跨瀏覽器差異。
若同一 Tomcat 部署多個 WebApp (不同 ContextPath),切勿將 Cookie Path 設為 `/`。否則所有應用都能讀寫該 Cookie,極易造成:
解決方案:各應用使用各自的 ContextPath 作為 Cookie Path (如 `/appA`、 `/appB`),或使用獨立域名/子域名隔離。
防禦 CSRF 攻擊的關鍵屬性,標準 Servlet API 暫無直接 setter,需透過回應標頭手動設定或使用框架封裝:
// 手動設定 SameSite=Lax (平衡安全與體驗) 或 Strict (最嚴格)
response.addHeader("Set-Cookie", "userToken=abc123; Path=/app; HttpOnly; Secure; SameSite=Lax");
| 特性 | Cookie | LocalStorage | SessionStorage |
|---|---|---|---|
| 容量 | ~4KB | ~5MB | ~5MB |
| 自動隨請求發送 | 是 | 否 | 否 |
| 過期控制 | 伺服器/客戶端 | 手動清除/永久 | 分頁關閉清除 |
| 適用場景 | 身份識別、Token、追蹤 | 客戶端緩存、偏好設定 | 表單暫存、單分頁流程 |
Java 操作 Cookie API 簡單,但 Path、Domain、MaxAge、Secure、HttpOnly、SameSite 這六大屬性的正確組合才是生產環境穩定運作的關鍵。牢記「刪除即覆蓋,屬性必一致」,統一路徑管理,配合現代安全屬性,即可避開 90% 的 Cookie 相關坑。