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

深入理解 Cookie 與 Session:機制、差異與最佳實踐

     編輯:Java 綜合教學

核心概念

特性CookieSession
儲存位置客戶端(瀏覽器)伺服器端(記憶體/資料庫/Redis)
資料大小限制單個 4KB,域名下約 20-50 個理論無上限,受限於伺服器記憶體
安全性低(可被竄改、攔截、XSS 盜取)高(客戶端僅持有 Session ID)
生命週期可設定過期時間,持久化至硬碟預設 30 分鐘無活動失效,可配置
跨域支援需設定 Domain、SameSite需共享 Session 存儲(Redis/資料庫)

Cookie 運作機制

建立與儲存

// 伺服器端建立 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

Session 運作機制

建立與獲取

HttpSession session = request.getSession(); // 等同 getSession(true)
// 首次呼叫:建立新 Session,生成唯一 JSESSIONID
// 後續呼叫:根據 Cookie 中的 JSESSIONID 尋找現有 Session

內部流程

  1. 用戶首次請求 → 伺服器建立 HttpSession 物件,生成 JSESSIONID。
  2. 伺服器回應頭設定:Set-Cookie: JSESSIONID=xxx; Path=/; HttpOnly。
  3. 瀏覽器儲存 Cookie。
  4. 後續請求自動攜帶 JSESSIONID。
  5. 伺服器根據 ID 從 Session 存儲中取出對應物件。

Session 域物件對比

域物件生命週期適用場景
request單次請求請求轉發傳遞資料
session用戶會話期間用戶登入狀態、購物車、權限資訊
application (ServletContext)整個應用生命週期全域配置、線上人數統計、緩存資料

Cookie 被禁用時的應對:URL 重寫

當瀏覽器禁用 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)。

Session 管理最佳實踐

1. 設定超時時間

// web.xml
<session-config><session-timeout>30</session-timeout></session-config>

// 程式碼動態設定(秒)
session.setMaxInactiveInterval(1800);

2. 登出銷毀 Session

session.invalidate(); // 移除伺服器端 Session 資料
// 建議同時清除客戶端 Cookie
Cookie cookie = new Cookie("JSESSIONID", "");
cookie.setMaxAge(0);
cookie.setPath("/");
response.addCookie(cookie);

3. 序列化支援叢集/重啟保持

  • Session 中存放的物件必須實作 Serializable。
  • Tomcat 預設將 Session 序列化至 work/Catalina/localhost/[context]/SESSION.ser。
  • 叢集環境建議使用 Redis、Memcached 或資料庫共享 Session。

4. 安全強化

  • HttpOnly:防止 XSS 竊取 Session ID。
  • Secure:僅 HTTPS 傳輸,防止中間人攻擊。
  • SameSite=Strict/Lax:防禦 CSRF 攻擊。
  • 定期輪換 Session ID(登入成功後 session.regenerateId())。

常見問題 FAQ

Q: request.getSession() 與 request.getSession(true) 差異?
A: 完全相同。若 Session 不存在則建立新的;若存在則返回現有。
Q: request.getSession(false) 用途?
A: 僅獲取現有 Session,不存在時返回 null,不建立新 Session。適用於檢查登入狀態。
Q: 為何 Session 有時會丟失?
A: 1) 瀏覽器禁用 Cookie 且未啟用 URL 重寫。2) Session 超時。3) 應用重啟且未配置 Session 持久化。4) 叢集環境未共享 Session。
Q: Session 能儲存多大資料?
A: 理論無上限,但建議單個 Session < 100KB,避免記憶體壓力與序列化效能問題。大物件應存放於快取,Session 僅存引用 ID。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved