SecurityContextPersistenceFilter
大约 4 分钟
SecurityContextPersistenceFilter
SecurityContextPersistenceFilter
是 Spring Security
中的一个过滤器,主要负责持久化和恢复与当前请求相关的安全上下文(SecurityContext
)。
SecurityContext
是什么?
1、SecurityContext
是 Spring Security 用来保存当前用户安全信息的容器,通常包含以下内容:
- Authentication:代表当前用户的认证信息,如用户名、角色、权限等。
- Authorities:用户拥有的权限或角色。
SecurityContextHolder
:用于存储当前线程的SecurityContext
。
Spring Security
将安全上下文与当前请求生命周期关联,因此每个请求处理期间,Spring Security 会将该请求的安全上下文保持在 SecurityContextHolder
中,并且在请求结束后,将其清除。
SecurityContextPersistenceFilter
的作用
2、SecurityContextPersistenceFilter
主要有两个功能:
- 恢复
SecurityContext
:每次请求到达时,SecurityContextPersistenceFilter
会从HttpSession
中恢复先前保存的SecurityContext
。这样做是为了确保每个请求都可以访问到正确的认证信息。 - 清除
SecurityContext
:在请求处理结束时,SecurityContextPersistenceFilter
会从SecurityContextHolder
清除SecurityContext
,防止信息泄露给后续的请求。
SecurityContextPersistenceFilter
的工作原理
3、SecurityContextPersistenceFilter
的工作流程可以简要描述为以下几个步骤:
请求开始时:
SecurityContextPersistenceFilter
负责检查HttpSession
是否存在有效的SecurityContext
,如果存在,它会将该SecurityContext
恢复到当前线程中的SecurityContextHolder
请求处理时:
- 当前请求的
SecurityContext
会被存储在SecurityContextHolder
中,通常包含当前用户的认证信息。其他Spring Security
组件(如AuthenticationManager
或UsernamePasswordAuthenticationFilter
)可能会使用这些信息来处理安全性相关的操作。
请求结束时:
- 在请求处理结束时,
SecurityContextPersistenceFilter
会确保清除SecurityContextHolder
中的SecurityContext
,防止线程池或后续请求中泄漏安全上下文。
4、配置和使用
SecurityContextPersistenceFilter
默认是由 Spring Security 自动配置和管理的,通常我们不需要显式地去配置它。这个过滤器会自动添加到 Spring Security 的过滤器链中,并且它会作为过滤器链中的第一个过滤器之一,以确保在其他过滤器之前进行安全上下文的恢复。
典型的配置
SecurityContextPersistenceFilter
是由 Spring Security 自动配置的,通常不会需要显式的配置。不过,如果需要定制,可以通过以下方式来进行调整:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.addFilterBefore(new MyCustomFilter(), SecurityContextPersistenceFilter.class)
.authorizeRequests()
.anyRequest().authenticated();
return http.build();
}
SecurityContextHolder
和 HttpSession
的关系
5、与 SecurityContextHolder
:SecurityContextHolder
是 Spring Security 的核心类之一,它用于持有当前线程的SecurityContext
。SecurityContextPersistenceFilter
会在每次请求时,将SecurityContext
设置到SecurityContextHolder
中,处理完请求后再清除。HttpSession
:SecurityContext
通常会保存在HttpSession
中,这样用户在多个请求之间保持认证信息。如果使用Stateless
模式(例如JWT
),SecurityContextPersistenceFilter
就不会从HttpSession
中恢复信息,而是通过其他方式(如请求头)来维持用户身份。
SecurityContextPersistenceFilter
的工作流程
6、- 恢复 SecurityContext:
- 通过
SecurityContextRepository
(默认是HttpSessionSecurityContextRepository
)从HttpSession
中加载存储的SecurityContext
。 SecurityContextPersistenceFilter
会把恢复的SecurityContext
放入SecurityContextHolder
中。
- 通过
- 清除 SecurityContext:
- 请求结束后,
SecurityContextPersistenceFilter
会清除当前线程中的SecurityContextHolder
中的SecurityContext
。
- 请求结束后,
7、相关类和接口
SecurityContextRepository
:这是一个接口,负责存储和加载SecurityContext
。默认实现是HttpSessionSecurityContextRepository
,它将SecurityContext
存储在HttpSession
中。HttpSessionSecurityContextRepository
:这是默认的SecurityContextRepository
实现,它会将SecurityContext
存储在HttpSession
中。这是最常见的存储方式,适用于基于会话的认证机制。Stateless Authentication
:如果你的应用是无状态的(如使用 JWT 或其他 token 机制),你可以自定义SecurityContextRepository
,并配置 Spring Security 不使用HttpSession
存储SecurityContext
。
8、常见问题和注意事项
- 会话过期/丢失:如果用户的
HttpSession
过期或者被清除,SecurityContextPersistenceFilter
将无法从会话中恢复SecurityContext
。在这种情况下,通常会导致用户被强制注销或需要重新认证。 - 多线程环境:由于
SecurityContext
是绑定到当前线程的,SecurityContextPersistenceFilter
在每个请求中会为当前线程恢复或清除安全上下文。在线程池中使用时需要小心,因为SecurityContext
可能被错误地共享到其他线程中。 - Stateless 应用:在无状态(stateless)应用中,通常不使用
HttpSession
来存储SecurityContext
。此时,你可能会使用基于请求头(如 Bearer Token)的认证方式,而不依赖会话存储。