SessionManagementFilter
大约 5 分钟
SessionManagementFilter
1、概述
SessionManagementFilter
主要用于管理和控制与用户会话相关的安全策略。它的核心职责是确保会话的管理符合安全要求,比如防止会话固定攻击(Session Fixation)以及对会话的并发访问进行限制。
2、作用
SessionManagementFilter
主要用于:
- 会话固定攻击防护:在用户登录后,确保会话 ID 不会被攻击者利用(比如通过恶意链接获得)。
- 并发会话控制:限制每个用户的并发会话数,防止用户在多个设备或浏览器中同时登录。
- 会话超时处理:配置会话的有效期,控制用户的会话过期时间。
3、工作流程
SessionManagementFilter
的工作流程可以分为以下几个步骤:
3.1、Session Fixation Protection
- 会话固定攻击是指攻击者通过操控用户的会话 ID 来冒充用户登录。攻击者可能在用户登录之前就将会话 ID 设为已知的某个值,从而在用户登录后接管会话。
- 为了防止这种攻击,
SessionManagementFilter
默认启用了会话固定攻击保护。它会在用户认证成功后,强制改变会话 ID,确保用户的会话 ID 在认证后不可预测。 - 默认情况下,Spring Security 使用
SessionFixationProtectionStrategy
作为防护策略,常见的做法是执行会话重定向(例如,通过HttpServletRequest.changeSessionId()
来改变会话 ID)。
3.2、Session Timeout Management
- 会话超时是指当用户长时间未活动时,Spring Security 会终止用户会话。
SessionManagementFilter
可以根据配置的会话过期时间,自动检测并管理会话的生命周期。当会话过期时,用户的会话会被销毁,用户将被迫重新认证。- 配置
sessionTimeout
可以通过HttpSecurity
配置,例如设置会话的最大空闲时间。
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.invalidSessionUrl("/session-invalid") // 会话失效后重定向的 URL
.maximumSessions(1) // 限制并发会话数
.maxSessionsPreventsLogin(true); // 如果达到最大会话数,禁止登录新会话
}
}
SpringSecurity6.x
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withUsername("user")
.password("{noop}password")
.roles("USER")
.build()
);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.sessionManagement()
.maximumSessions(1) // 限制同一时间只有一个会话
.maxSessionsPreventsLogin(true); // 达到最大会话数时阻止登录
return http.build();
}
}
3.3、Concurrent Session Control
- 通过
SessionManagementFilter
,可以配置并发会话控制,例如限制同一用户在多个地方的登录数量。 - 配置
maximumSessions
可以指定同一个用户最多允许多少个并发会话。比如,如果你不希望一个用户在多个设备上同时登录,可以通过maximumSessions(1)
来限制每个用户最多只能有一个会话。
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.maximumSessions(1) // 限制并发会话数为 1
.maxSessionsPreventsLogin(true); // 如果达到最大会话数,则禁止新会话登录
}
}
maximumSessions
:设置最大允许并发会话数。maxSessionsPreventsLogin
:如果该参数为true
,则在达到最大会话数时,新的会话无法登录。如果为false
,则新会话会被创建,旧会话会被踢出。
3.4、Session Invalidity Handling
- 当会话无效时(例如会话超时或手动注销时),
SessionManagementFilter
会重定向用户到配置的invalidSessionUrl
或执行适当的会话失效处理。 - 你可以通过
invalidSessionUrl("/session-invalid")
配置一个 URL,当会话失效时,用户会被重定向到这个 URL。
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.invalidSessionUrl("/session-invalid"); // 会话失效后跳转到该 URL
}
}
4、配置
SessionManagementFilter
的配置通常通过 HttpSecurity
的 sessionManagement()
方法进行。常见的配置选项包括:
invalidSessionUrl()
:设置会话无效时的跳转 URL。maximumSessions()
:设置并发会话数限制。maxSessionsPreventsLogin()
:配置达到最大会话数时的行为。sessionFixation()
:设置会话固定攻击的保护策略。常见的值包括:SessionFixationProtectionStrategy
:通过改变会话 ID 防止会话固定攻击(默认策略)。newSession()
:创建新的会话 ID,防止攻击者利用固定会话 ID。none()
:不进行会话固定保护。
4.1、配置示例
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.invalidSessionUrl("/session-invalid") // 会话失效后的跳转 URL
.maximumSessions(1) // 限制并发会话数为 1
.maxSessionsPreventsLogin(true) // 达到最大会话数时禁止新会话登录
.sessionFixation().newSession() // 使用新会话防止会话固定攻击
.and()
.authorizeRequests()
.antMatchers("/login", "/register").permitAll()
.anyRequest().authenticated();
}
}
4.2、SpringSecurity 6.x 并发会话控制
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withUsername("user")
.password("{noop}password")
.roles("USER")
.build()
);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.sessionManagement()
.maximumSessions(1) // 限制同一时间只有一个会话
.maxSessionsPreventsLogin(true); // 达到最大会话数时阻止登录
return http.build();
}
}
4.2、SpringSecurity 6.x 会话超时控制
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
return new InMemoryUserDetailsManager(
User.withUsername("user")
.password("{noop}password")
.roles("USER")
.build()
);
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.sessionManagement()
.invalidSessionUrl("/session-invalid") // 会话失效后跳转的 URL
.sessionFixation().newSession() // 会话固定攻击防护
.maximumSessions(1) // 限制并发会话数
.maxSessionsPreventsLogin(true) // 达到最大会话数时禁止登录新会话
.and()
.and()
.httpBasic(); // 启用 HTTP 基本认证
return http.build();
}
}
5、核心类和接口
SessionManagementFilter
:核心过滤器,负责管理会话的生命周期,包括会话固定攻击保护、会话超时、并发会话控制等。SessionFixationProtectionStrategy
:默认的会话固定攻击保护策略,负责在认证后更换会话 ID。ConcurrentSessionControlStrategy
:用于控制并发会话数的策略。InvalidSessionStrategy
:当会话无效时执行的策略,通常是重定向到指定的 URL。SessionAuthenticationStrategy
:处理用户会话的策略,用于确保用户会话的一致性和安全性。
总结
SessionManagementFilter
是 Spring Security 中负责会话管理的核心过滤器,提供了防止会话固定攻击、并发会话控制和会话超时等功能。- 通过
HttpSecurity
配置,你可以细粒度地控制会话的行为,确保用户会话的安全性。 - 主要功能包括会话 ID 更换、并发会话数限制、会话失效处理等。
- 对于需要加强会话管理的应用,
SessionManagementFilter
提供了多种防护机制,能够有效提升系统的安全性。