HTTP 無狀態,Session 在服務端為每個瀏覽器會話創建唯一上下文,通過 JSESSIONID Cookie 或 URL 重寫維持身份。本文系統講解生命周期、核心 API、Cookie 禁用應對、安全登出最佳實踐。
// 獲取或創建 Session HttpSession session = request.getSession(); // 等同 getSession(true) HttpSession session = request.getSession(false); // 僅獲取,不創建 // 判斷是否新建 boolean isNew = session.isNew();
| 方法 | 說明 |
|---|---|
setAttribute(name, value) | 存入對象(建議可序列化) |
getAttribute(name) | 取出對象,需強轉 |
removeAttribute(name) | 移除單個屬性 |
getAttributeNames() | 枚舉所有屬性名 |
invalidate() | 銷毀整個 Session,釋放資源 |
getId() | 獲取 JSESSIONID |
getCreationTime() / getLastAccessedTime() | 創建/最後訪問時間戳 |
setMaxInactiveInterval(seconds) | 設置超時(秒),負數永不過期 |
// Request: 單次請求鏈(forward/include)
request.setAttribute("k", "v");
// Session: 同一瀏覽器多請求
session.setAttribute("k", "v");
// Application (ServletContext): 全應用共享
getServletContext().setAttribute("k", "v");
容器將 JSESSIONID 附加到 URL 路徑參數中:
原始: /app/servlet 重寫: /app/servlet;jsessionid=ABC123DEF
<!-- 表單 action 重寫 -->
<form action="<%= response.encodeURL("saveServlet") %>" method="post">
<!-- 超鏈接重寫 -->
<a href="<%= response.encodeURL("getServlet") %>">查看數據</a>
<!-- 重定向重寫 -->
response.sendRedirect(response.encodeRedirectURL("target.jsp"));
JSESSIONIDencodeURL 自動攜帶 ID 提交public void logout(HttpServletRequest req, HttpServletResponse resp) throws IOException {
HttpSession session = req.getSession(false);
if (session != null) {
session.invalidate(); // 核心:銷毀服務端 Session 對象
}
resp.sendRedirect(req.getContextPath() + "/login.jsp");
}
public void secureLogout(HttpServletRequest req, HttpServletResponse resp) throws IOException {
HttpSession session = req.getSession(false);
if (session != null) {
// 1. 清除業務數據
session.removeAttribute("user");
// 2. 設置極短超時,強制過期
session.setMaxInactiveInterval(1);
// 3. 徹底銷毀
session.invalidate();
}
// 4. 客戶端清除 Cookie(可選)
Cookie cookie = new Cookie("JSESSIONID", "");
cookie.setMaxAge(0);
cookie.setPath(req.getContextPath());
resp.addCookie(cookie);
resp.sendRedirect(req.getContextPath() + "/login.jsp");
}
request.changeSessionId() (Servlet 3.1+) 或銷毀舊 Session 創建新 SessionHttpOnly、Secure (HTTPS)、SameSite=Strict| 方案 | 原理 | 優點 | 缺點 |
|---|---|---|---|
| Sticky Session | Nginx ip_hash 綁定節點 | 簡單,無代碼改動 | 單點故障,擴容難 |
| Session 複製 | Tomcat DeltaManager/BackupManager | 透明化 | 網絡開銷大,節點多性能差 |
| Redis 共享 | Spring Session + Redis | 高可用、水平擴展、多語言 | 引入外部依賴、序列化開銷 |
| JWT 無狀態 | 客戶端攜帶簽名 Token | 完全無狀態、橫向擴展極簡 | 無法主動撤銷、Token 體積大 |
<session-config>
<session-timeout>30</session-timeout> <!-- 分鐘 -->
<cookie-config>
<http-only>true</http-only>
<secure>true</secure>
<same-site>STRICT</same-site>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode> <!-- 禁用 URL 重寫 -->
</session-config>
掌握 Session 本質是「服務端狀態 + 客戶端憑證」,配合安全配置與分佈式方案,構建企業級會話管理體系。