HTTP 是無狀態協議,每次請求都是獨立的。為了識別用戶身份、維持登入狀態、購物車功能等,我們需要會話追蹤技術。Cookie 和 Session 是兩種最主流的解決方案。
伺服器在響應頭中設置 Set-Cookie,瀏覽器儲存後,後續請求會自動攜帶該 Cookie。適用於輕量級數據儲存,如「記住我」、用戶偏好設定。
| 屬性 | 說明 |
|---|---|
| Domain/Path | 控制 Cookie 的作用範圍 |
| Max-Age/Expires | 控制生命週期,Session Cookie 隨瀏覽器關閉銷毀 |
| Secure | 僅 HTTPS 傳輸 |
| HttpOnly | 防止 XSS 攻擊,JavaScript 無法讀取 |
| SameSite | 防禦 CSRF 攻擊 |
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
Cookie[] cookies = request.getCookies();
String name = getCookieValue(cookies, "username");
if (name == null) {
Cookie cookie = new Cookie("username", "user123");
cookie.setMaxAge(60 * 60 * 24 * 7); // 7天
cookie.setHttpOnly(true);
response.addCookie(cookie);
out.println("首次訪問,已設置 Cookie");
} else {
out.println("歡迎回來," + name);
}
}
private String getCookieValue(Cookie[] cookies, String key) {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(key)) {
return cookie.getValue();
}
}
}
return null;
}
Session 數據存儲在伺服器內存(或 Redis/Memcached),客戶端僅保存 Session ID(通常為 JSESSIONID Cookie)。解決了 Cookie 帶寬開銷大、安全性差的問題。
request.getSession()setAttribute/getAttributeinvalidate()、伺服器關閉單機 Session 無法支撐集群環境,主流方案:
| 維度 | Cookie | Session |
|---|---|---|
| 存儲位置 | 客戶端 | 伺服端 |
| 數據安全性 | 低(可被竄改/竊取) | 高 |
| 存儲容量 | 4KB/域 | 受限於伺服器內存 |
| 適用場景 | 非敏感、輕量數據 | 用戶身份、權限、購物車 |
// 表單生成時
String token = UUID.randomUUID().toString();
session.setAttribute("form_token", token);
// 頁面隱藏域: <input type="hidden" name="token" value="${token}">
// 提交驗證
String submittedToken = request.getParameter("token");
String sessionToken = (String) session.getAttribute("form_token");
if (sessionToken != null && sessionToken.equals(submittedToken)) {
session.setAttribute("form_token", UUID.randomUUID().toString()); // 更新 token
// 業務處理
} else {
// 重複提交或非法請求
}
理解 Cookie 與 Session 的本質差異,根據業務場景選擇合適方案。現代 Web 開發中,建議採用「Session 存核心狀態 + Cookie 存非敏感偏好」的混合策略,並配合 Redis 實現分散式 Session 共享。