工具類功能總覽
| 方法 | 功能 | 關鍵參數 |
| addCookie | 新增 Cookie | key、value、路徑、有效期(30天) |
| deleteCookie | 刪除 Cookie | key、路徑一致性、立即失效 |
| getCookieValue | 獲取 Cookie 值 | key、UTF-8 解碼 |
完整實作代碼
package com.example.web.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Cookie 處理工具類
* 統一管理 Cookie 生命週期、編碼與路徑策略
*/
public class CookieUtil {
/** Cookie 預設路徑:全域有效 */
private static final String DEFAULT_PATH = "/";
/** Cookie 預設有效期:30 天(秒) */
private static final int DEFAULT_MAX_AGE = 60 * 60 * 24 * 30;
/** 預設編碼 */
private static final String DEFAULT_ENCODING = "UTF-8";
/**
* 新增 Cookie
* @param response 回應物件
* @param key Cookie 名稱
* @param value Cookie 值(自動 UTF-8 編碼建議由調用方處理)
*/
public static void addCookie(HttpServletResponse response, String key, String value) {
Cookie cookie = new Cookie(key, value);
cookie.setPath(DEFAULT_PATH);
cookie.setMaxAge(DEFAULT_MAX_AGE);
// 建議生產環境啟用:cookie.setSecure(true); // 僅 HTTPS 傳輸
// cookie.setHttpOnly(true); // 防 XSS 攻擊
response.addCookie(cookie);
}
/**
* 刪除 Cookie
* @param request 請求物件(用於獲取現有 Cookie 驗證)
* @param response 回應物件
* @param key 要刪除的 Cookie 名稱
*/
public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String key) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (key.equals(cookie.getName())) {
Cookie deleteCookie = new Cookie(key, null);
deleteCookie.setPath(DEFAULT_PATH); // 必須與創建時路徑一致
deleteCookie.setMaxAge(0); // 立即失效
response.addCookie(deleteCookie);
break; // 找到即刪除,避免重複
}
}
}
}
/**
* 獲取 Cookie 值(自動 UTF-8 解碼)
* @param request 請求物件
* @param key Cookie 名稱
* @return 解碼後的值,不存在返回 null
* @throws UnsupportedEncodingException 編碼不支援異常
*/
public static String getCookieValue(HttpServletRequest request, String key)
throws UnsupportedEncodingException {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (key.equals(cookie.getName())) {
return URLDecoder.decode(cookie.getValue(), DEFAULT_ENCODING);
}
}
}
return null;
}
}
核心設計要點解析
路徑一致性原則
刪除 Cookie 時路徑必須與創建時完全一致。瀏覽器根據「域名+路徑+名稱」唯一標識 Cookie,路徑不匹配將導致刪除失效。本工具類統一使用 DEFAULT_PATH = "/" 確保一致性。
編碼處理策略
- 寫入時:建議調用方預先進行 URL 編碼(
URLEncoder.encode(value, "UTF-8")),避免特殊字符導致解析錯誤
- 讀取時:工具類自動執行
URLDecoder.decode,確保獲取原始值
安全屬性建議(生產環境必加)
// 生產環境建議配置
cookie.setSecure(true); // 僅 HTTPS 傳輸,防中間人攻擊
cookie.setHttpOnly(true); // 禁止 JavaScript 訪問,防 XSS
cookie.setDomain(".example.com"); // 跨子域名共享(可選)
使用示例
@Controller
public class UserController {
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String rememberMe,
HttpServletResponse response) {
// 登入成功,寫入記憶帳號 Cookie(30天)
if ("true".equals(rememberMe)) {
CookieUtil.addCookie(response, "remember_user", username);
}
return "redirect:/dashboard";
}
@GetMapping("/logout")
public String logout(HttpServletRequest request, HttpServletResponse response) {
// 登出時清除記憶帳號
CookieUtil.deleteCookie(request, response, "remember_user");
return "redirect:/login";
}
@GetMapping("/profile")
public String profile(HttpServletRequest request, Model model)
throws UnsupportedEncodingException {
// 讀取記憶帳號自動填充
String rememberedUser = CookieUtil.getCookieValue(request, "remember_user");
model.addAttribute("username", rememberedUser);
return "profile";
}
}
常見坑點與解決方案
| 問題 | 原因 | 解決方案 |
| 刪除無效 | 路徑/域名不匹配 | 統一路徑常量,創建與刪除使用相同路徑 |
| 中文亂碼 | 編碼不一致 | 寫入 URLEncoder.encode,讀取 URLDecoder.decode,統一 UTF-8 |
| 跨子域無效 | Domain 未設置 | 設置 cookie.setDomain(".parent.com") |
| HTTPS 下丟失 | Secure 屬性缺失 | 生產環境啟用 cookie.setSecure(true) |
擴展建議
- 新增
addCookie(HttpServletResponse, String, String, int maxAge) 支援自定義有效期
- 提供
getCookieMap(HttpServletRequest) 批量獲取所有 Cookie
- 整合簽名機制(HMAC)防止 Cookie 竄改
- 支援 SameSite 屬性(CSRF 防護)