Servlet Session 跟踪

四种会话跟踪方案、HttpSession 的用法与失效策略。

Intermediate
Key Points容器用 JSESSIONID 把多次请求关联到同一个 HttpSession;Session 存在服务端,Cookie 里只放 ID。

HTTP 是无状态的

Between two requests the server does not know you. To "remember" a user, the client must send the same identifier every time; the four approaches differ only in where that identifier lives.

ApproachWherePros / Cons
Cookie客户端 Cookie简单、自动携带;可被禁用
HttpSession服务端 + Cookie 里的 ID安全、容量大;占服务端内存
URL rewritingURL 的 ;jsessionid=Cookie 禁用时可用;URL 难看易泄露
Hidden field表单隐藏字段只对表单提交有效

HttpSession 基本用法

Java
@WebServlet("/cart")
public class CartServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        req.setCharacterEncoding("UTF-8");
        HttpSession session = req.getSession();          // 没有就创建
        String item = req.getParameter("item");

        @SuppressWarnings("unchecked")
        List<String> cart = (List<String>) session.getAttribute("cart");
        if (cart == null) {
            cart = new ArrayList<>();
            session.setAttribute("cart", cart);
        }
        if (item != null && !item.isBlank()) {
            cart.add(item);
        }
        resp.setContentType("text/plain;charset=UTF-8");
        resp.getWriter().println("购物车:" + cart);
    }
}

getSession() equals getSession(true): create if absent. To query without creating, use getSession(false), which returns null when there is none — mandatory in auth checks, or every request silently spawns a session.

Session 的常用操作

Java
HttpSession s = req.getSession(false);
if (s != null) {
    s.setAttribute("uid", 42);                        // 存
    Object uid = s.getAttribute("uid");               // 取
    s.removeAttribute("uid");                         // 删单个
    s.invalidate();                                   // 销毁整个会话(登出)
    String id = s.getId();                            // JSESSIONID 的值
    long created = s.getCreationTime();
    int timeout = s.getMaxInactiveInterval();         // 秒
}

超时与失效

XML
<session-config>
  <session-timeout>30</session-timeout>   <!-- 单位:分钟 -->
  <cookie-config>
    <http-only>true</http-only>
    <secure>true</secure>
  </cookie-config>
  <tracking-mode>COOKIE</tracking-mode>
</session-config>
  • 默认 30 分钟无活动即失效,从最后一次请求算起
  • setMaxInactiveInterval(-1) 表示永不过期,生产环境不要用
  • 登出时 invalidate(),不要只 removeAttribute
Sessions live in container memory by default: a restart loses them all, and two servers do not share them. For durability or clustering you need session persistence or a central store such as Redis, or users get logged out at random.

登出与防固定攻击

Java
// 登出:销毁旧会话
HttpSession old = req.getSession(false);
if (old != null) old.invalidate();

// 登录成功后换一个新会话,防会话固定攻击
HttpSession fresh = req.getSession(true);
req.changeSessionId();          // 或直接 invalidate 后 getSession(true)
fresh.setAttribute("uid", user.getId());

Friends & Partners