核心 API
new Cookie(name, value):建立
response.addCookie(cookie):寫入回應
request.getCookies():讀取(回傳陣列,可能為 null)
cookie.setMaxAge(seconds):生命週期(負數=瀏覽器關閉銷毀,0=立即刪除)
cookie.setPath("/"):作用路徑(預設當前路徑,建議設根路徑)
cookie.setDomain(".example.com"):跨子域共享
cookie.setSecure(true):僅 HTTPS 傳輸
cookie.setHttpOnly(true):防 XSS,JS 無法讀取
封裝工具類
public final class CookieUtil {
private CookieUtil() {}
public static void add(HttpServletResponse resp, String name, String value, int maxAge) {
Cookie c = new Cookie(name, value);
c.setPath("/");
if (maxAge > 0) c.setMaxAge(maxAge);
c.setHttpOnly(true);
c.setSecure(true); // 僅 HTTPS 環境
resp.addCookie(c);
}
public static String get(HttpServletRequest req, String name) {
Cookie[] cookies = req.getCookies();
if (cookies == null) return null;
for (Cookie c : cookies) if (name.equals(c.getName())) return c.getValue();
return null;
}
public static void remove(HttpServletResponse resp, String name) {
Cookie c = new Cookie(name, null);
c.setPath("/");
c.setMaxAge(0);
resp.addCookie(c);
}
}
Map 封裝進階版
private static Map toMap(HttpServletRequest req) {
Map map = new HashMap<>();
Cookie[] cookies = req.getCookies();
if (cookies != null) for (Cookie c : cookies) map.put(c.getName(), c);
return map;
}
public static Cookie getCookie(HttpServletRequest req, String name) {
return toMap(req).get(name);
}
安全與合規清單
- 敏感資料絕不存 Cookie(Token、密碼、個資)
- 啟用
HttpOnly + Secure + SameSite=Strict/Lax
- 設定合理
Max-Age,避免永久 Cookie
- 定期輪換 Session ID,登出時刪除 Cookie
- GDPR/個資法:告知用途、取得同意、提供拒絕機制
常見坑
getCookies() 回傳 null 而非空陣列 → 必須 null 檢查
- 路徑不匹配導致讀不到 → 統一
setPath("/")
- 中文值需
URLEncoder.encode / URLDecoder.decode
- 同名 Cookie 多個路徑/域名 → 瀏覽器送回順序不定,勿依賴