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

Java Servlet 讀寫瀏覽器 Cookie 完整實戰:工具類、編碼、刪除、SameSite 全覽

     編輯:Java 相關知識

Cookie 基礎回顧

  • **本質**:Server 通過 Set-Cookie 響應頭寫入瀏覽器,瀏覽器後續請求自動攜帶 Cookie 請求頭。
  • **屬性**:Name、Value、Domain、Path、Max-Age/Expires、Secure、HttpOnly、SameSite (Lax/Strict/None)。
  • **限制**:單域名 ≤ 400 個,單 Cookie ≤ 4KB,總大小 ≤ 4MB。

通用工具類 CookieUtils(生產級)

public final class CookieUtils {
    private CookieUtils() {}

    /** 讀取指定名稱的 Cookie 值(自動 URL 解碼) */
    public static String getValue(HttpServletRequest request, String name) {
        Cookie cookie = getCookie(request, name);
        if (cookie == null) return null;
        try {
            return URLDecoder.decode(cookie.getValue(), StandardCharsets.UTF_8.name());
        } catch (Exception e) {
            return cookie.getValue(); // 解碼失敗返回原值
        }
    }

    /** 獲取 Cookie 對象 */
    public static Cookie getCookie(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null) return null;
        for (Cookie c : cookies) {
            if (c.getName().equals(name)) return c;
        }
        return null;
    }

    /** 獲取所有 Cookie 轉 Map */
    public static Map getAll(HttpServletRequest request) {
        Map map = new LinkedHashMap<>();
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie c : cookies) {
                map.put(c.getName(), c.getValue());
            }
        }
        return map;
    }

    /** 寫入 Cookie(自動 URL 編碼、設置 Path=/、HttpOnly、SameSite=Lax) */
    public static void add(HttpServletResponse response, String name, String value, int maxAgeSeconds) {
        try {
            value = URLEncoder.encode(value, StandardCharsets.UTF_8.name());
        } catch (Exception ignored) {}
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setHttpOnly(true);           // 防 XSS
        cookie.setMaxAge(maxAgeSeconds);    // -1: 會話級; 0: 刪除; >0: 持久化秒數
        cookie.setSecure(false);            // 僅 HTTPS 時改 true
        // SameSite 需 Servlet 4.0+ (Tomcat 9+, Jetty 10+)
        try {
            Method m = cookie.getClass().getMethod("setAttribute", String.class, String.class);
            m.invoke(cookie, "SameSite", "Lax"); // CSRF 防護
        } catch (Exception ignored) {}
        response.addCookie(cookie);
    }

    /** 刪除 Cookie(必須同名、同 Path、同 Domain) */
    public static void remove(HttpServletRequest request, HttpServletResponse response, String name) {
        Cookie cookie = getCookie(request, name);
        if (cookie != null) {
            cookie.setMaxAge(0);
            cookie.setPath("/");
            response.addCookie(cookie);
        }
    }

    /** 刪除所有 Cookie */
    public static void clearAll(HttpServletRequest request, HttpServletResponse response) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie c : cookies) {
                c.setMaxAge(0);
                c.setPath("/");
                response.addCookie(c);
            }
        }
    }
}

實戰場景示例

1. 登錄記住我(持久化 30 天)

@PostMapping("/login")
public Result login(@RequestParam String username, 
                    @RequestParam String password,
                    @RequestParam(required = false) Boolean remember,
                    HttpServletResponse response) {
    User user = userService.authenticate(username, password);
    // 生成 Token 或 Session...
    if (Boolean.TRUE.equals(remember)) {
        CookieUtils.add(response, "remember_token", tokenService.generatePersistentToken(user), 30 * 24 * 3600);
    }
    return Result.ok();
}

2. 登出清理

@PostMapping("/logout")
public Result logout(HttpServletRequest request, HttpServletResponse response) {
    session.invalidate();
    CookieUtils.clearAll(request, response);
    return Result.ok();
}

3. 多標籤頁共享會話(Session Cookie,MaxAge=-1)

CookieUtils.add(response, "JSESSIONID", sessionId, -1); // 瀏覽器關閉即失效

編碼與中文處理

  • Cookie 值 **不允許** 空格、分號、逗號、等號等特殊字符,**必須 URL 編碼**。
  • 工具類統一使用 UTF-8 編碼/解碼,確保中文、Emoji 正確存取。
  • 若使用 Spring @CookieValue,框架自動解碼,無需手動處理。

SameSite 屬性深度解析

值行為適用場景
Strict完全禁止第三方攜帶(連結跳轉也不帶)高安全操作(修改密碼、轉賬)
Lax允許鏈接跳轉、GET 表單攜帶,禁止 POST/iframe/圖片請求**大多數業務 Cookie 推薦默認**
None無限制,**必須配合 Secure=true (HTTPS)**跨域嵌入、第三方登錄、CDN 資源

工具類默認 Lax,兼容 CSRF 防護與正常導航。需 None 時手動調用 cookie.setAttribute("SameSite", "None") 並確保 setSecure(true)。

瀏覽器開發者工具驗證

  1. Chrome DevTools → Application → Cookies → 域名。
  2. 2. 查看 Name/Value/Domain/Path/Expires/Size/HttpOnly/Secure/SameSite 列。 3. Network → 請求頭 Cookie / 響應頭 Set-Cookie 驗證傳輸內容。

總結

掌握 CookieUtils 封裝的 **讀/寫/刪/清** 四大核心操作、URL 編碼規範、SameSite 防 CSRF 策略,即可應對 99% 的 Servlet 端 Cookie 業務場景。建議將工具類納入項目公共模塊,統一 Cookie 安全基線(HttpOnly=true, SameSite=Lax, Path=/)。

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