bigywater.tech
Spring · 105

Session 与 SecurityContextRepository:登录态存在哪里

登录态到底存在哪里?session id 登录后为什么会变?STATELESS 是什么效果?自己写的登录接口为什么下次请求又要登录?这篇在 Spring Boot 4.0.8、Spring Security 7 上手动带 cookie 逐步验证。

SPRING_SECURITY_CONTEXT
登录态存在服务端 HttpSession 的这个属性里,cookie 里只有 session id
302 vs 200
自定义登录接口不保存 SecurityContext,随后 /who 是 302;保存之后是 200
1800 秒
默认 session 超时 maxInactiveInterval

登录态在哪里

实测 · 本机执行输出
  未登录 GET /who → HTTP 302,Location http://127.0.0.1:9601/login
  访问 /login 页面时拿到的 JSESSIONID 前 8 位 = 6122A52D(没有登录的会话);POST /login → HTTP 302,Location http://127.0.0.1:9601/who?continue;登录之后的 JSESSIONID 前 8 位 = A5EAB0DE(与登录前不同)
  登录响应的 Set-Cookie:JSESSIONID=A5EAB0DEAE7119559F5937ABD8809275; Path=/; HttpOnly
  GET /who → 用户=alice,session=A5EAB0DE
  GET /sess → session 属性 [SPRING_SECURITY_CONTEXT, SPRING_SECURITY_SAVED_REQUEST],SPRING_SECURITY_CONTEXT 的类型=SecurityContextImpl,maxInactiveInterval=1800 秒

服务端 HttpSession;cookie 只有 JSESSIONID(HttpOnly,没有 Secure 与 SameSite)。

会话固定防护

实测 · 本机执行输出
  sessionFixation().none():登录前 33D57952,登录后 33D57952,没有变

默认登录后换 session id;none() 会让 id 不变。

无状态

实测 · 本机执行输出
  带 Basic 的 GET /who → HTTP 200 用户=alice,session=没有;响应有 Set-Cookie:False
  不带凭据再请求一次 → HTTP 401(服务端什么都没记住)

STATELESS 不创建会话,每个请求都要带凭据。

自定义登录接口

实测 · 本机执行输出
  GET /api/login-nosave → HTTP 200 已认证 alice,没有保存;本请求内 SecurityContextHolder 里是 alice;Set-Cookie 条数 0
    随后带着 Cookie GET /who → HTTP 302,Location http://127.0.0.1:9604/login
  GET /api/login-save → HTTP 200 已认证 alice,并保存到 SecurityContextRepository;本请求内 SecurityContextHolder 里是 alice;Set-Cookie 条数 1
    随后带着 Cookie GET /who → HTTP 200,用户=alice,session=A7AEFDBE

要显式 saveContext 到 SecurityContextRepository,否则下个请求就没登录。

退出

实测 · 本机执行输出
  POST /logout → HTTP 302,Location http://127.0.0.1:9604/login?logout;响应 Set-Cookie:[]
  拿着退出前的旧 Cookie 再 GET /who → HTTP 302,Location http://127.0.0.1:9604/login

POST /logout 让 session 作废,旧 cookie 再访问被跳回登录页。

分步演示

登录态
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(Spring Security 7)。用户 alice / pw(spring.security.user.*);客户端是 Python http.client,不自动跟随重定向,手动保存并带上 JSESSIONID;表单登录的 CSRF 令牌从登录页面里解析;SecurityFilterChain 由 -Dx105.cfg 切换(default、fixnone、stateless)
    • 没有验证:Redis 等外部存储里的 Spring Session;并发会话控制(maximumSessions);session 超时之后的行为;remember-me(见第 114 篇);SameSite 与 Secure 的配置(server.servlet.session.cookie.*);集群里 session 粘性;会话固定攻击的实际演示;HttpSessionSecurityContextRepository 与 RequestAttributeSecurityContextRepository 的差别
    京ICP备2026067502号-1京公网安备11010502063487号