spring security 过滤器链相关初始化过程
Spring Security 的过滤器链(Filter Chain)初始化流程是其安全机制的核心实现,其设计目标是按特定顺序组装多个安全过滤器,形成一个完整的请求处理链。以下从 源码层面 和 配置流程 分析其初始化逻辑:
一、初始化流程概览
Spring Security 过滤器链的初始化由 FilterChainProxy
驱动,其核心流程可分为以下步骤:
-
触发自动配置
Spring Boot 通过spring-boot-starter-security
引入SpringSecurityFilterChain
自动配置类,触发SecurityFilterChain
的构建。 -
加载
WebSecurityConfiguration
通过@EnableWebSecurity
注解激活WebSecurityConfiguration
配置类,初始化WebSecurity
对象。 -
构建
HttpSecurity
调用WebSecurityConfigurerAdapter#init
方法,创建HttpSecurity
实例,并加载所有配置的SecurityFilterChain
。 -
组装过滤器链
HttpSecurity
将配置的过滤器按 固定顺序 添加到链中,最终生成SecurityFilterChain
对象。 -
注册
FilterChainProxy
WebSecurity
将多个SecurityFilterChain
封装到FilterChainProxy
,并注册到 Servlet 容器的过滤器链中。
二、源码级流程分析
1. 入口:WebSecurityConfiguration
• 通过 @Bean
创建 SpringSecurityFilterChain
(即 FilterChainProxy
):
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
return webSecurity.build(); // 最终生成 FilterChainProxy
}
2. WebSecurity
的构建
• WebSecurity
继承自 AbstractConfiguredSecurityBuilder
,通过 build()
方法触发初始化:
public final O build() throws Exception {
// 调用所有 WebSecurityConfigurerAdapter 的 init() 和 configure()
for (SecurityBuilder<?> securityBuilder : securityBuilders) {
securityBuilder.build();
}
// 生成 FilterChainProxy
return performBuild();
}
3. HttpSecurity
的配置
• HttpSecurity
继承自 AbstractConfiguredSecurityBuilder
,通过 addFilter(Filter)
方法按顺序添加过滤器:
public HttpSecurity addFilter(Filter filter) {
// 根据过滤器类型确定插入位置
Integer order = this.filterOrders.getOrder(filter.getClass());
this.filters.add(order, filter);
return this;
}
4. 过滤器顺序管理
• 所有过滤器的顺序由 FilterOrderRegistration
类预定义,例如:
private FilterOrderRegistration() {
addFilterToOrder(ChannelProcessingFilter.class, 0);
addFilterToOrder(WebAsyncManagerIntegrationFilter.class, 1);
addFilterToOrder(SecurityContextPersistenceFilter.class, 2);
addFilterToOrder(HeaderWriterFilter.class, 3);
// ... 其他过滤器的顺序定义
}
三、配置流程详解
1. 默认过滤器链
Spring Security 默认加载以下核心过滤器(按顺序):
过滤器名称 | 作用 | 顺序 |
---|---|---|
ChannelProcessingFilter | 处理协议切换(HTTP/HTTPS) | 0 |
WebAsyncManagerIntegrationFilter | 集成异步请求上下文 | 1 |
SecurityContextPersistenceFilter | 存储/恢复 SecurityContext | 2 |
HeaderWriterFilter | 写入安全响应头(如 CSP、HSTS) | 3 |
CsrfFilter | CSRF 防护 | 4 |
LogoutFilter | 处理注销请求 | 5 |
UsernamePasswordAuthenticationFilter | 表单登录认证 | 6 |
DefaultLoginPageGeneratingFilter | 生成默认登录页 | 7 |
BasicAuthenticationFilter | HTTP Basic 认证 | 8 |
RequestCacheAwareFilter | 缓存请求(用于重定向后恢复) | 9 |
SecurityContextHolderAwareRequestFilter | 包装 ServletRequest 增强安全方法 | 10 |
AnonymousAuthenticationFilter | 匿名用户身份填充 | 11 |
SessionManagementFilter | 会话管理(如并发控制) | 12 |
ExceptionTranslationFilter | 处理安全异常(如认证/授权异常) | 13 |
FilterSecurityInterceptor | 最终授权决策(允许/拒绝请求) | 14 |
2. 自定义过滤器链
通过 HttpSecurity
的配置方法添加或覆盖过滤器:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new StatsFilter(), BasicAuthenticationFilter.class)
.csrf().disable(); // 移除 CsrfFilter
}
3. 多过滤器链配置
可定义多个 SecurityFilterChain
,针对不同 URL 路径应用不同过滤器链:
@Bean
public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests().anyRequest().authenticated()
.and().addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public SecurityFilterChain defaultFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().permitAll();
return http.build();
}
四、初始化流程调试
1. 查看已加载的过滤器
在日志中启用 DEBUG
级别,观察过滤器链的加载顺序:
logging.level.org.springframework.security=DEBUG
输出示例:
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
...
]
2. 关键断点位置
• FilterChainProxy#doFilterInternal
:观察请求如何匹配过滤器链。
• HttpSecurity#addFilter
:跟踪自定义过滤器的插入位置。
• WebSecurity#build
:查看最终生成的 FilterChainProxy
。
五、核心设计思想
- 责任链模式:每个过滤器处理特定安全任务,职责单一。
- 可插拔性:通过
HttpSecurity
动态添加/移除过滤器。 - 优先级控制:通过预定义的顺序保证过滤器执行逻辑正确(例如
SecurityContextPersistenceFilter
必须在认证过滤器之前执行)。 - 多链支持:允许为不同的 URL 路径配置独立的安全规则。
六、常见问题
1. 过滤器顺序错误
• 现象:自定义过滤器未按预期顺序执行。
• 解决:通过 addFilterBefore()
或 addFilterAfter()
显式指定位置。
2. 过滤器未生效
• 原因:未将过滤器添加到正确的 SecurityFilterChain
。
• 排查:检查 URL 路径匹配规则和过滤器的注册位置。
3. 性能问题
• 优化点:通过 WebSecurity#ignoring()
忽略静态资源路径,避免不必要的过滤器执行。
通过理解过滤器链的初始化流程,开发者可以更高效地定制安全策略,并快速定位安全配置相关的问题。