首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java Cookie 操作全攻略:建立、讀取、刪除與跨路徑機制深度解析

     編輯:Java 程式設計入門

前言

Cookie 是 HTTP 無狀態特性下維持會話狀態的關鍵機制。雖然現代開發常使用 JWT、Session + Redis 等方案,但 Cookie 仍是瀏覽器端狀態管理的基石。本文系統整理 Java Servlet 中 Cookie 的建立、讀取、刪除操作,並深入剖析 Path (路徑) 屬性對 Cookie 可見性與生命週期的影響,這是許多開發者容易踩坑的地方。

核心 API 快速上手

1. 建立與寫入 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);

2. 讀取 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。

3. 刪除 Cookie

核心原則:刪除 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);

深度解析:Path 屬性與瀏覽器匹配機制

Cookie 的 `Path` 屬性決定了瀏覽器在發送請求時是否攜帶該 Cookie。許多「刪除無效」、「跨模組共享失敗」的問題根源皆在於對 Path 機制理解不透徹。

路徑匹配規則

  • 瀏覽器發送請求時,會比對 請求路徑是否以 Cookie Path 為前綴。
  • 例如 Cookie Path = `/app/user`,請求 `/app/user/profile` 會攜帶,請求 `/app/admin` 則不會。
  • 預設 Path 為建立該 Cookie 的 Servlet 請求路徑 (含 ContextPath)。

刪除時的「向上查找」行為差異 (瀏覽器實作不同)

當嘗試刪除一個「當前路徑不存在、但父路徑存在」的同名 Cookie 時,不同瀏覽器表現不一:

場景Firefox (FF)Internet Explorer (IE)
鍵名全小寫 (如 `key`) 若當前路徑無,向上遞歸查找父路徑並刪除最近的一個 向上查找父路徑 (但會跳過某些層級,行為較不可預期)
鍵名含大寫/混合 (如 `Key`、`USER_ID`) 同小寫,向上查找 不向上查找,僅嘗試刪除當前路徑,找不到則放棄
最佳實踐: 建立、讀取、刪除 Cookie 時,永遠顯式指定 `setPath("/")` 或固定的應用根路徑 (如 `/app`),且鍵名統一使用小寫。避免依賴瀏覽器的向上查找行為,消除跨瀏覽器差異。

多 Web 應用共享 Tomcat 時的坑

若同一 Tomcat 部署多個 WebApp (不同 ContextPath),切勿將 Cookie Path 設為 `/`。否則所有應用都能讀寫該 Cookie,極易造成:

  • 用戶在應用 A 登入,應用 B 讀到同名 Cookie 誤以為已登入。
  • 應用 A 登出刪除 Cookie,導致應用 B 用戶莫名其妙登出。

解決方案:各應用使用各自的 ContextPath 作為 Cookie Path (如 `/appA`、 `/appB`),或使用獨立域名/子域名隔離。

進階:安全屬性與現代最佳實踐

SameSite 屬性 (Servlet API 2.6+ / Spring Boot 2.5+)

防禦 CSRF 攻擊的關鍵屬性,標準 Servlet API 暫無直接 setter,需透過回應標頭手動設定或使用框架封裝:

// 手動設定 SameSite=Lax (平衡安全與體驗) 或 Strict (最嚴格)
response.addHeader("Set-Cookie", "userToken=abc123; Path=/app; HttpOnly; Secure; SameSite=Lax");
  • Strict:完全禁止第三方請求攜帶 Cookie (連結跳轉也不攜帶)。
  • Lax:允許安全的第三方請求 (如 GET 連結跳轉) 攜帶,推薦預設值。
  • None:允許所有跨站請求,必須搭配 Secure (HTTPS)。

Cookie vs LocalStorage vs SessionStorage

特性CookieLocalStorageSessionStorage
容量~4KB~5MB~5MB
自動隨請求發送是否否
過期控制伺服器/客戶端手動清除/永久分頁關閉清除
適用場景身份識別、Token、追蹤客戶端緩存、偏好設定表單暫存、單分頁流程

總結

Java 操作 Cookie API 簡單,但 Path、Domain、MaxAge、Secure、HttpOnly、SameSite 這六大屬性的正確組合才是生產環境穩定運作的關鍵。牢記「刪除即覆蓋,屬性必一致」,統一路徑管理,配合現代安全屬性,即可避開 90% 的 Cookie 相關坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved