| 特性 | Cookie | Session |
|---|---|---|
| 儲存位置 | 客戶端(瀏覽器) | 伺服器端(記憶體/資料庫/Redis) |
| 資料大小限制 | 單個 4KB,域名下約 20-50 個 | 理論無上限,受限於伺服器記憶體 |
| 安全性 | 低(可被竄改、攔截、XSS 盜取) | 高(客戶端僅持有 Session ID) |
| 生命週期 | 可設定過期時間,持久化至硬碟 | 預設 30 分鐘無活動失效,可配置 |
| 跨域支援 | 需設定 Domain、SameSite | 需共享 Session 存儲(Redis/資料庫) |
// 伺服器端建立 Cookie
Cookie cookie = new Cookie("userId", "12345");
cookie.setMaxAge(60 * 60 * 24 * 7); // 7 天有效,持久化至硬碟
cookie.setPath("/"); // 整個域名有效
cookie.setHttpOnly(true); // 防止 JS 讀取,防禦 XSS
cookie.setSecure(true); // 僅 HTTPS 傳輸
response.addCookie(cookie);
儲存位置(Windows 7+):
C:\Users\[用戶]\AppData\Roaming\Microsoft\Windows\Cookies\C:\Users\[用戶]\AppData\Roaming\Microsoft\Windows\Cookies\Low\若未設定 MaxAge,Cookie 為「會話級」,儲於記憶體,瀏覽器關閉即銷毀。
瀏覽器對同域名請求自動附帶 Cookie:
Cookie: JSESSIONID=2DB77EDB2964DFC61828ECBCC8076258; userId=12345
HttpSession session = request.getSession(); // 等同 getSession(true) // 首次呼叫:建立新 Session,生成唯一 JSESSIONID // 後續呼叫:根據 Cookie 中的 JSESSIONID 尋找現有 Session
HttpSession 物件,生成 JSESSIONID。Set-Cookie: JSESSIONID=xxx; Path=/; HttpOnly。JSESSIONID。| 域物件 | 生命週期 | 適用場景 |
|---|---|---|
| request | 單次請求 | 請求轉發傳遞資料 |
| session | 用戶會話期間 | 用戶登入狀態、購物車、權限資訊 |
| application (ServletContext) | 整個應用生命週期 | 全域配置、線上人數統計、緩存資料 |
當瀏覽器禁用 Cookie,伺服器無法透過 Cookie 傳遞 JSESSIONID。解決方案:將 Session ID 附加在 URL 中。
// 原始 URL https://localhost/Web/B?name=zz // 重寫後 https://localhost/Web/B;jsessionid=2DB77EDB2964DFC61828ECBCC8076258?name=zz
關鍵差異:jsessionid 以分號 ; 分隔路徑,而非問號 ?,不屬於查詢參數。
Servlet 容器自動支援:response.encodeURL(url)、response.encodeRedirectURL(url)。
// web.xml <session-config><session-timeout>30</session-timeout></session-config> // 程式碼動態設定(秒) session.setMaxInactiveInterval(1800);
session.invalidate(); // 移除伺服器端 Session 資料
// 建議同時清除客戶端 Cookie
Cookie cookie = new Cookie("JSESSIONID", "");
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);
Serializable。work/Catalina/localhost/[context]/SESSION.ser。HttpOnly:防止 XSS 竊取 Session ID。Secure:僅 HTTPS 傳輸,防止中間人攻擊。SameSite=Strict/Lax:防禦 CSRF 攻擊。session.regenerateId())。request.getSession() 與 request.getSession(true) 差異?request.getSession(false) 用途?null,不建立新 Session。適用於檢查登入狀態。