Spring Security 教程(10)、处理登出

基本登出配置

logout 配图
logout 配图
logout 配图

Spring Security 默认提供登出功能,登出 URL 是 /logout。

1
2
3
4
5
6
http.logout()
.logoutUrl("/logout") // 登出请求的 URL
.logoutSuccessUrl("/login?logout") // 登出成功后的跳转 URL
.invalidateHttpSession(true) // 销毁 Session
.deleteCookies("JSESSIONID") // 删除指定 Cookie
.logoutSuccessHandler(logoutSuccessHandler); // 自定义登出处理器

登出流程

  1. 用户发送 GET 请求到 /logout
  2. Spring Security 验证 CSRF Token(如果启用了 CSRF 防护)
  3. 调用所有注册的 LogoutHandler:
    • SessionInvalidatingLogoutHandler:销毁 HTTP Session
    • CookieClearingLogoutHandler:删除指定 Cookie
    • SecurityContextLogoutHandler:清除 SecurityContext
  4. 调用 LogoutSuccessHandler,跳转到成功页面

防止 CSRF 攻击的登出

登出操作是状态改变的操作,必须受 CSRF 防护。如果关闭了 CSRF 防护,攻击者可以构造一个页面,当用户访问时自动发起登出请求。

1
2
// 正确的做法:不关闭 CSRF,而是为登出请求添加 Token
// 或者使用 POST 方法代替 GET

自定义登出成功处理

1
2
3
4
http.logout()
.logoutSuccessHandler((request, response, authentication) -> {
response.sendRedirect("/");
});

并发 Session 控制

Spring Security 可以限制同一个账号同时登录的数量:

1
2
3
http.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true); // 超出限制时,新的登录请求被拒绝

或者让旧会话失效,允许新会话:

1
2
3
http.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired"); // 旧会话过期后跳转到此 URL

登出后的安全清理

登出时,确保清理所有安全相关的状态:

  • Session 数据(敏感信息不应留在 Session 中)
  • SecurityContext(当前用户的认证信息)
  • Remember-Me Cookie(自动登录 Cookie)
  • 任何自定义的安全 Cookie

这防止了用户在不安全设备(如公共电脑)上登出后,其他用户利用残留的 Session 或 Cookie 冒充该用户。