Spring Security 默认配置源码分析
在 Spring Security 的官方文档中,说明了,它的配置为以下的默认实现。
1 |
|
说明一下什么是使用表单的授权方式,什么是使用基本授权方式,注意这里的授权其实是认证))
表单认证是基于页面表单的用户身份验证方式,适用于传统 Web 应用(有前端页面的场景)。默认行为就会自动生成一个简单的登录页面(包含用户名输入框、密码输入框、提交按钮)。
可以按照下面这样自定义配置:
1 | http.formLogin(form -> form |
HTTP Basic 认证就是基本认证,是基于 HTTP
协议规范的认证方式,适用于 API
接口(无前端页面的场景),通过请求头传递认证信息。当未认证用户访问受保护资源时,服务器不会重定向到登录页,而是返回
401 Unauthorized 响应,并在响应头中添加
WWW-Authenticate: Basic realm="Realm"
。
客户端(如浏览器、Postman、前端 Ajax)收到响应后,会弹出一个系统级别的登录弹窗(由浏览器 / 客户端生成,非自定义页面)。认证信息通过 HTTP 头传递(Base64 编码,不加密,生产环境需配合 HTTPS 使用)。无默认登出机制(需手动清除请求头或关闭客户端)。
而默认的15(16)个过滤器就是这些,好像我注销了一个配置,就有一个没装上

在 Spring Security
中,这些默认的过滤器在不同的配置器(Configurer
)中被创建和配置,然后由HttpSecurity
进行统一管理和组装,最终形成DefaultSecurityFilterChain
。关于这个的内容下面会细说
Spring Security 的自动配置
HttpSecurity 中加载了什么
之前我们讲解的初始化配置只是在很简单的层面上做了一些介绍,方便后面的学习,在这里我们将有条理的分析整个Spring Security 自动配置
HttpSecurity
是 Spring Security 中配置 HTTP
安全规则的核心入口类
HttpSecurity
这个 bean
算是最基础的底层配置了,它是Spring
Security各种配置的基础,这个bean是Spring
Security自动加载的,并且同时会默认帮我们完成了Spring
Security完整功能的各项配置,我们先找到这个bean加载的位置:
在HttpSecurityConfiguration
类中,加载了HttpSecurity


Spring Security 对 Web 应用的保护,本质是对 “HTTP 请求”
的拦截与规则校验 。HttpSecurity
就是负责定义这些
“拦截规则” 的核心类,包括:
哪些请求需要认证?
由
AuthorizeHttpRequestsConfigurer
实现,AuthorizeHttpRequestsConfigurer
是处理请求授权的核心配置器,其内部的AuthorizationManagerRequestMatcherRegistry
提供了requestMatchers()
、permitAll()
、authenticated()
等方法,用于定义 “哪些请求需要认证”。1
2
3
4
5
6
7
8
9
10
11// HttpSecurity 中与请求授权相关的方法
public HttpSecurity authorizeHttpRequests(Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeHttpRequestsCustomizer) throws Exception {
ApplicationContext context = this.getContext();
// 获取或创建 AuthorizeHttpRequestsConfigurer 配置器
AuthorizeHttpRequestsConfigurer<HttpSecurity> configurer = (AuthorizeHttpRequestsConfigurer) this.getOrApply(new AuthorizeHttpRequestsConfigurer(context));
// 通过 Customizer 自定义授权规则(如哪些路径允许匿名、哪些需要认证)
authorizeHttpRequestsCustomizer.customize(configurer.getRegistry());
return this;
}实际开发中,我们通过链式调用配置规则,例如
1
2
3
4
5http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll() // 公开路径,无需认证
.requestMatchers("/admin/**").hasRole("ADMIN") // 管理员角色可访问
.anyRequest().authenticated() // 其他请求必须认证
);- 这些配置最终会转换为
Filter
(如FilterSecurityInterceptor
),在请求到达时拦截并校验权限。
- 这些配置最终会转换为
用什么方式认证(表单登录、HTTP Basic、OAuth2 等)?
HttpSecurity
通过不同的配置器支持多种认证方式,以下是最常用的几种:表单登录(
formLogin
)1
2
3
4
5
6
7
8// 表单登录配置方法
public HttpSecurity formLogin(Customizer<FormLoginConfigurer<HttpSecurity>> formLoginCustomizer) throws Exception {
// 获取或创建 FormLoginConfigurer 配置器(负责表单登录逻辑)
FormLoginConfigurer<HttpSecurity> configurer = (FormLoginConfigurer) this.getOrApply(new FormLoginConfigurer());
// 自定义表单登录配置(如登录页URL、成功跳转页等)
formLoginCustomizer.customize(configurer);
return this;
}FormLoginConfigurer
是处理表单登录的配置器,负责:- 生成默认登录页(或指定自定义登录页
loginPage("/login")
); - 处理登录请求(默认
/login
)、成功 / 失败跳转; - 生成
UsernamePasswordAuthenticationFilter
过滤器,拦截登录请求并校验用户名密码。
- 生成默认登录页(或指定自定义登录页
HTTP Basic 认证
1
2
3
4
5
6
7
8// HTTP Basic 认证配置方法
public HttpSecurity httpBasic(Customizer<HttpBasicConfigurer<HttpSecurity>> httpBasicCustomizer) throws Exception {
// 获取或创建 HttpBasicConfigurer 配置器(负责HTTP Basic认证)
HttpBasicConfigurer<HttpSecurity> configurer = (HttpBasicConfigurer) this.getOrApply(new HttpBasicConfigurer());
// 自定义HTTP Basic配置(如 Realm 名称)
httpBasicCustomizer.customize(configurer);
return this;
}OAuth2 登录
1
2
3
4
5
6// OAuth2 登录配置方法(第三方登录,如GitHub、微信)
public HttpSecurity oauth2Login(Customizer<OAuth2LoginConfigurer<HttpSecurity>> oauth2LoginCustomizer) throws Exception {
OAuth2LoginConfigurer<HttpSecurity> configurer = (OAuth2LoginConfigurer) this.getOrApply(new OAuth2LoginConfigurer());
oauth2LoginCustomizer.customize(configurer);
return this;
}OAuth2LoginConfigurer
用于配置 OAuth2/OpenID Connect 登录,支持第三方认证;- 会生成
OAuth2LoginAuthenticationFilter
,处理 OAuth2 回调请求并完成认证。
认证后如何授权(基于角色、权限)?
授权逻辑与 “哪些请求需要认证” 同属一个配置器,核心是通过
AuthorizationManager
校验用户权限是否匹配请求要求。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// AuthorizeHttpRequestsConfigurer 内部类,用于定义授权规则
public class AuthorizationManagerRequestMatcherRegistry {
// 例如:配置某个路径需要特定角色
public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
// 内部会创建基于角色的 AuthorizationManager
return this.access(this.roleHierarchyAuthoritiesMapper(role));
}
// 配置某个路径允许匿名访问
public AuthorizationManagerRequestMatcherRegistry permitAll() {
return this.access(AuthenticatedAuthorizationManager.permitAll());
}
// 配置其他请求必须认证
public AuthorizationManagerRequestMatcherRegistry authenticated() {
return this.access(AuthenticatedAuthorizationManager.authenticated());
}
}- 授权规则最终会转换为
AuthorizationManager
(权限管理器),在请求拦截时校验:- 用户是否拥有
hasRole("ADMIN")
要求的角色; - 请求是否符合
permitAll()
(无需认证)或authenticated()
(必须认证)。
- 用户是否拥有
- 底层由
FilterSecurityInterceptor
过滤器执行校验,不通过则抛出AccessDeniedException
。
- 授权规则最终会转换为
如何处理跨站请求伪造(CSRF)、会话、异常?
1
2
3
4
5
6
7
8
9// CSRF 防护配置方法
public HttpSecurity csrf(Customizer<CsrfConfigurer<HttpSecurity>> csrfCustomizer) throws Exception {
ApplicationContext context = this.getContext();
// 获取或创建 CsrfConfigurer 配置器(负责CSRF防护)
CsrfConfigurer<HttpSecurity> configurer = (CsrfConfigurer) this.getOrApply(new CsrfConfigurer(context));
// 自定义CSRF配置(如开启/关闭、令牌存储方式)
csrfCustomizer.customize(configurer);
return this;
}如何处理会话?
sessionManagement
配置1
2
3
4
5
6
7
8// 会话管理配置方法
public HttpSecurity sessionManagement(Customizer<SessionManagementConfigurer<HttpSecurity>> sessionManagementCustomizer) throws Exception {
// 获取或创建 SessionManagementConfigurer 配置器(负责会话管理)
SessionManagementConfigurer<HttpSecurity> configurer = (SessionManagementConfigurer) this.getOrApply(new SessionManagementConfigurer());
// 自定义会话配置(如会话创建策略、超时时间)
sessionManagementCustomizer.customize(configurer);
return this;
}如何处理异常
exceptionHandling
配置1
2
3
4
5
6
7
8// 异常处理配置方法
public HttpSecurity exceptionHandling(Customizer<ExceptionHandlingConfigurer<HttpSecurity>> exceptionHandlingCustomizer) throws Exception {
// 获取或创建 ExceptionHandlingConfigurer 配置器(负责异常处理)
ExceptionHandlingConfigurer<HttpSecurity> configurer = (ExceptionHandlingConfigurer) this.getOrApply(new ExceptionHandlingConfigurer());
// 自定义异常处理(如认证失败、授权失败的响应)
exceptionHandlingCustomizer.customize(configurer);
return this;
}ExceptionHandlingConfigurer
用于配置认证 / 授权过程中的异常处理,例如:- 认证失败(
authenticationEntryPoint
):配置未认证用户访问受保护资源时的响应(如跳转登录页或返回 401 JSON); - 授权失败(
accessDeniedHandler
):配置已认证用户权限不足时的响应(如跳转拒绝页或返回 403 JSON)。
- 认证失败(
- 会生成
ExceptionTranslationFilter
过滤器,捕获并处理认证 / 授权异常。
所以说,HttpSecurity
基于建造者模式设计,同时通过
配置器(Configurer)对不同安全模块进行解耦,上面说的都是配置器,每个配置器负责一个细分领域的配置
然后这些配置器最终会生成对应的Filter
(过滤器),由HttpSecurity
统一组装为DefaultSecurityFilterChain
,在
HTTP 请求到达时按顺序拦截并应用规则,实现对 Web 应用的安全保护。
设计元素 | 作用 |
---|---|
建造者(Builder) | HttpSecurity 本身实现
SecurityBuilder ,负责最终构建
DefaultSecurityFilterChain |
配置器(Configurer) | 每个配置器对应一个安全模块(如 FormLoginConfigurer
负责表单登录,CsrfConfigurer 负责 CSRF 防护),通过
HttpSecurity 的 xxxConfigurer() 方法接入 |
然后,HttpSecurity
通过不同的配置器,覆盖了 Web
安全的全场景需求,以下是最常用的配置器:
配置器方法 | 对应配置器类 | 核心能力 |
---|---|---|
formLogin() |
FormLoginConfigurer |
配置表单登录(自定义登录页、成功跳转、失败处理等) |
authorizeHttpRequests() |
AuthorizeHttpRequestsConfigurer |
配置请求授权规则(基于角色、权限、IP 等控制访问) |
csrf() |
CsrfConfigurer |
配置CSRF 防护(开启 / 关闭、自定义令牌等) |
logout() |
LogoutConfigurer |
配置登出逻辑(登出 URL、成功跳转、清除会话等) |
sessionManagement() |
SessionManagementConfigurer |
配置会话管理(会话创建策略、超时时间、并发控制等) |
httpBasic() |
HttpBasicConfigurer |
配置HTTP Basic 认证(适合 API 场景) |
oauth2Login() |
OAuth2LoginConfigurer |
配置OAuth2 登录(第三方登录,如 GitHub、微信) |
exceptionHandling() |
ExceptionHandlingConfigurer |
配置异常处理(认证失败、授权失败的页面或 JSON 响应) |
HttpSecurity自动装配的流程
我们一点一点来看看,Spring Security 都帮我们怎么进行了
HttpSecurity
的默认配置了

1 | // HttpSecurityConfiguration 中创建 HttpSecurity 的核心方法 |
首先初始化了AuthenticationManagerBuilder
,httpSecurity
是重新new了一个authenticationManagerBuilder
的,并且我们初始化的authenticationManager
是放在
builder 对象里的parentAuthenticationManager
属性里的。
然后我们看到httpSecurity
的构造方法

可以发现是往一个所谓的共享对象的 Map
容器中放入了authenticationManagerBuilder
对象
1 | this.setSharedObject(AuthenticationManagerBuilder.class, authenticationBuilder); |
初始化的时候还放入了spring上下文对象

可以发现httpSecurity
的sharedObjects
属性里放入了所谓需要共享的对象,另外注意这里requestMatcherConfigurer
这个属性也进行了初始化。
接下来就是使用httpSecurity
进行了默认配置,在
HttpSecurity
中,通过 getOrApply
方法来获取或应用配置器(如
CsrfConfigurer
)。往上看你就会发现几乎所有的配置器都调用的了这个方法进行装配

- 首先尝试从已有的配置器中获取指定类型(这里是
CsrfConfigurer
类型)的配置器。 - 如果存在,直接返回;如果不存在,就调用
apply
方法来应用这个新的配置器。
而 apply
方法会进一步调用 add
方法,将配置器添加到 configurers
集合中(configurers
是
AbstractConfiguredSecurityBuilder
中的一个
LinkedHashMap
,用于存储各种配置器),这样就完成了配置器的注册,后续可以基于这些配置器来构建安全过滤链等安全相关功能。这里实际上就是将上面
new 的 configure 放入了 configurers属性中了。
接下来我们来看过滤器是如何装配的
addFilter
方法顾名思义就是添加过滤器的方法

- 首先从
filterOrders
中获取要添加的过滤器(如WebAsyncManagerIntegrationFilter
)对应的顺序。filterOrders
是FilterOrderRegistration
类型的对象,内部维护了过滤器类与顺序的映射关系。 - 如果获取不到顺序,会抛出异常,提示需要使用
addFilterBefore
或addFilterAfter
来指定过滤器顺序;如果获取到顺序,就将过滤器包装成OrderedFilter
(包含过滤器实例和顺序)并添加到filters
列表中。
最后装完的filters
是一个
ArrayList
,用于存储所有添加的过滤器(包装为
OrderedFilter
形式,带有顺序信息)。在构建安全过滤链时,这些过滤器会按照顺序被组织起来,对
HTTP
请求进行安全处理,比如身份验证、授权、跨站请求伪造(CSRF)防护等。
1 | private List<OrderedFilter> filters = new ArrayList(); |
而决定其过滤器顺序的就是filterOrders
, 是
FilterOrderRegistration
类型,其内部通过
filterToOrder
等结构维护了不同过滤器类对应的顺序。在
FilterOrderRegistration
的构造方法中,会为各种 Spring
Security 内置的过滤器(如
CsrfFilter
、LogoutFilter
、UsernamePasswordAuthenticationFilter
等)预先注册好顺序,这样在添加过滤器时,就能根据过滤器类获取到对应的顺序,从而保证过滤器在过滤链中有正确的执行顺序。
这样,不同的过滤器就会按照预先定义的顺序在请求处理流程中依次执行,确保 Spring Security 各项安全功能按正确逻辑生效。
总结一下就是,httpSecurity
默认初始化会出事后一个authenticationManager
对象并放入一个authenticationManagerBuilder
对象中,随后这个
builder 对象会放入 httpSecurity 对象的
sharedObjects
属性中; 然后 httpSecurity
会创建类如csrf,exceptionHandling等等的配置器,随后也放入 sharedObjects
属性中。额案后将配置器添加到 configurers
集合中,之后再搭建过滤器链,从 filterOrders
中获取要添加的过滤器,在构建安全过滤链时,这些过滤器会按照顺序被组织起来,实现其功能,这样就联系上了前面进行的
16 个默认过滤器的装配和各种配置的初始化。
HttpSecurity如何构建过滤器链
HttpSecurity如何构建DefaultSecurityFilterChain过滤器链
那么其实HttpSecurity
的使命是构建
DefaultSecurityFilterChain
(安全过滤链),流程分为两步
配置阶段:通过配置器定义规则
开发者通过 HttpSecurity
提供的配置器方法(如
formLogin()
、authorizeHttpRequests()
),声明各类安全规则:
1 |
|
每个配置器(如
FormLoginConfigurer
、AuthorizeHttpRequestsConfigurer
)会将配置转换为具体的
Filter(过滤器),并注册到 HttpSecurity
中。
构建阶段:生成安全过滤链

当调用 http.build()
时,HttpSecurity
会执行:
- 收集所有配置器生成的 Filter;
- 按照预设顺序(由
FilterOrderRegistration
管理)排序 Filter; - 结合请求匹配规则(
RequestMatcher
),封装为DefaultSecurityFilterChain
; - 将
DefaultSecurityFilterChain
注册到 Spring Security 过滤器链中,对 HTTP 请求进行拦截校验。
我们展开说一下,HttpSecurity
继承自
AbstractConfiguredSecurityBuilder
,其 build()
方法会触发配置器的初始化和过滤器的收集。
收集所有配置器生成的 Filter
核心逻辑在 AbstractConfiguredSecurityBuilder
的
doBuild()
方法中,该方法会依次调用所有配置器(如
CsrfConfigurer
、FormLoginConfigurer
等)的
init()
和 configure()
方法,配置器在这些方法中生成对应的过滤器并添加到
HttpSecurity
的 filters
列表中。

1 |
|
配置器生成过滤器的示例(以 CsrfConfigurer
为例),CsrfConfigurer
在 configure()
方法中创建 CsrfFilter
并添加到 HttpSecurity
的过滤器列表:
1 |
|
按照预设顺序排序 Filter
然后来到了第二步,过滤器的排序由 FilterOrderRegistration
管理,最终在 HttpSecurity
的 performBuild()
方法中完成排序。
1 |
|
FilterOrderRegistration
预先定义了所有内置过滤器的顺序
封装为
DefaultSecurityFilterChain
排序完成后,HttpSecurity
会将过滤器列表与请求匹配规则(RequestMatcher
)结合,创建
DefaultSecurityFilterChain
实例。核心就是最后一步,前面都是排序
1 |
|

DefaultSecurityFilterChain
的构造方法如下
1 | public class DefaultSecurityFilterChain implements SecurityFilterChain { |
注册到 Spring Security 过滤器链
DefaultSecurityFilterChain
生成后,会被注册到
FilterChainProxy
中,而 FilterChainProxy
作为一个顶级过滤器(Filter
)被 Spring
容器管理,最终拦截所有 HTTP 请求并应用对应的安全过滤链。
FilterChainProxy
会根据请求匹配规则(RequestMatcher
)选择对应的
DefaultSecurityFilterChain
处理请求:
1 | public class FilterChainProxy extends GenericFilterBean { |
HttpSecurity如何初始化SecurityFilterChain过滤器链
先回忆一下 Spring Security
的过滤器叫FilterChainProxy
,其中存储过滤器的属性叫filterChains
,集合里元素的类型时SecurityFilterChain
:

因此,我们前面做了那么多,肯定是为了这个SecurityFilterChain
来做准备的,下面我们看
SpringBootWebSecurityConfiguration
这个类

进入到这个方法也是很熟悉啊,我们之前说的csrf()
、formLogin()
等配置方法 实现模式完全一致,也是做了通过
配置器(Configurer)
收集用户的安全配置的工作(如授权规则、CSRF
开关、登录页设置等),并在后续的 build()
阶段由配置器生成对应的过滤器,最终整合到安全过滤链中。
也是执行了getOrApply
来管理配置器
1 | public HttpSecurity authorizeHttpRequests(Customizer<AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry> authorizeHttpRequestsCustomizer) throws Exception { |
管中窥豹,我们可以得出,Spring Security 通过这种 “配置器模式 + 链式调用” 的设计,将分散的安全配置(授权、认证、防护等)统一管理,既保证了扩展性(可自定义配置器),又简化了使用方式(链式 API)。

从这个类结构图中我们不难发现,HttpSecurity
和AuthenticationManagerBuilder
都是这个
builder 类的子类,所以说实现的逻辑都是一样的,但是,我们
HttpSecurity
的构建就要复杂一点了
前面我们知道了,httpSecurity
初始化的时候创建了很多
configure 并且最终是放入到他的 map 集合中的,之前我们提到了
doBuild()
方法实现了配置器生成对应的过滤器然后装配的,那么核心的流程就涉及到init()
和 configure()
方法了,他们定义在
AbstractConfiguredSecurityBuilder
类中,是构建安全组件的核心方法。

init()
方法对所有已注册的
SecurityConfigurer
(如
CsrfConfigurer
、AuthorizeHttpRequestsConfigurer
等)进行初始化操作。在初始化阶段,配置器可以做一些前置准备工作,比如设置一些基础的配置参数、初始化内部依赖等,但还不会实际生成过滤器等核心安全组件。可以看到它在构建过程的早期阶段,为后续的配置阶段做准备。而
beforeinit()
则涉及到了更早期的操作,类似 AOP 的前置消息
1 | private void init() throws Exception { |
configure()
方法调用每个 SecurityConfigurer
的 configure
方法,让配置器根据用户的配置(比如授权规则、CSRF
防护开关等)来生成对应的安全组件,像各种过滤器(CsrfFilter
、FilterSecurityInterceptor
等)就是在这个阶段由配置器创建并添加到 HttpSecurity
的
filters
列表中的,可以看到他执行在 init()
方法执行之后,是配置器实际发挥作用、生成安全组件的关键阶段。
1 | private void configure() throws Exception { |
init
方法和configure
方法都是遍历的configurers
然后执行每一个configure
的配置方法的,configurers
是一个 存储所有安全配置器的容器,定义如下:
1 | // AbstractConfiguredSecurityBuilder 中定义 |
- 这是一个
LinkedHashMap
,键是配置器的类型(Class
),值是该类型的配置器列表(通常一个类型只有一个配置器)。 - 目的是按类型管理所有注册到
HttpSecurity
中的配置器(如CsrfConfigurer
、AuthorizeHttpRequestsConfigurer
等),方便后续遍历和操作。
init()
和 configure()
方法中遍历的
configurers
,正是通过 getConfigurers()
方法提取的:
1 | // AbstractConfiguredSecurityBuilder 中定义 |
- 作用:将
configurers
中按类型分组的配置器,汇总为一个扁平的Collection
,供init()
和configure()
遍历。 - 例如:如果注册了
CsrfConfigurer
、FormLoginConfigurer
、AuthorizeHttpRequestsConfigurer
,getConfigurers()
会返回包含这三个配置器的集合。
所有配置器(如 CsrfConfigurer
)都实现了
SecurityConfigurer
接口(通常继承
SecurityConfigurerAdapter
),因此都有 init()
和 configure()
方法。我们挑CsrfConfigurer
方法来实际看一下
在 HttpSecurity
中,通过 http.csrf()
方法触发 CsrfConfigurer
的创建与注册
1 | public CsrfConfigurer<HttpSecurity> csrf() throws Exception { |
getOrApply(new CsrfConfigurer(context))
:若已存在CsrfConfigurer
,直接返回;否则新建并注册到configurers
容器中。
CsrfConfigurer
虽未显式重写
init()
,但会继承父类 AbstractHttpConfigurer
的
init()
(空实现,可按需重写)。若有初始化逻辑,会在此阶段执行,新版本中,init()的流程貌似都交给了大家来处理
CsrfConfigurer
的 configure()
是核心,负责创建 CsrfFilter
并注册到
HttpSecurity
的过滤器链:
1 |
|
当调用 http.build()
时,进入 performBuild()
阶段,最终参与 SecurityFilterChain
构建:
1 | protected DefaultSecurityFilterChain performBuild() { |
这里我们看到,它先把
filter
里面的过滤器排序,遍历然后放入到sortedFilters
,最后创建了一个DefaultSecurityFilterChain
对象,至此,一个SecurityFilterChain
创建完毕,这里构造方法里还有个requestMatcher
属性留意一下,其实就是
Spring Security
的FilterChainProxy
中的filterChains
是一个集合,所以支持多个,那当有多个SecurityFilterChain
时,一个请求进来会使用哪个SecurityFilterChain
就是由这个requestMatcher
决定的
此时,一个完整的 SecurityFilterChain
诞生了:它包含
排序后的过滤器列表(如
CsrfFilter
、UsernamePasswordAuthenticationFilter
等)和
请求匹配规则(requestMatcher
)。
在 Spring Security 启动时,所有 HttpSecurity
构建的
DefaultSecurityFilterChain
会被收集到
FilterChainProxy
的 filterChains
集合中
当用户发送请求(如
POST /web/user
)时,流程进入运行阶段,核心是通过
requestMatcher
选择合适的过滤链:
所有请求会先经过 FilterChainProxy
的
doFilter
方法,这是 Spring Security 的 “守门人
FilterChainProxy
的 doFilter
方法接收请求(Spring Security 过滤链的 “总入口”),是请求进入 Spring
Security
过滤链的第一步,核心逻辑如下,它作为所有安全过滤逻辑的入口,通过
doFilterInternal
方法进入真正的过滤链匹配与执行流程

在 doFilterInternal
方法中,会调用
getFilters
方法筛选出与当前请求匹配的
SecurityFilterChain
, getFilters
方法遍历 filterChains
集合,通过每个链的
requestMatcher
判断是否匹配当前请求:
1 | private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { |

getFilters
方法会遍历所有
SecurityFilterChain
,通过 requestMatcher
判断是否匹配当前请求,一旦找到匹配的
SecurityFilterChain
,其包含的过滤器会按顺序执行
其中chain.matches(request)
—— 每个
SecurityFilterChain
都有自己的
requestMatcher
(请求匹配器),只有当请求与
requestMatcher
匹配时,才会使用该链的过滤器。

那么FilterChainsProxy
是从哪里来的呢,FilterChainProxy
是 Spring Security
过滤链的顶层代理过滤器,它的创建和注册与
WebSecurity
密切相关

WebSecurity
是 Spring Security
中管理全局安全过滤链的核心构建器(继承自
AbstractConfiguredSecurityBuilder
),它的
performBuild()
方法最终会创建 FilterChainProxy
实例,代码如下
1 | protected Filter performBuild() throws Exception { |
也就是说,FilterChainProxy
是 WebSecurity
在 performBuild()
方法中主动创建的,它的构造参数是所有收集到的
SecurityFilterChain
,而WebSecurity
本身的初始化和 FilterChainProxy
的创建,依赖于 Spring
Security 的自动配置机制,核心流程如下:
当我们在项目中添加
@EnableWebSecurity
注解时,会导入WebSecurityConfiguration
配置类,这个类是WebSecurity
的 “孵化器”。在
WebSecurityConfiguration
中,会通过@Bean
方法创建WebSecurity
对象,并为其配置必要的依赖(如ObjectPostProcessor
、ApplicationContext
等):然后,其中我们通过
SecurityConfiguration
中定义的SecurityFilterChain
Bean,会被WebSecurityConfiguration
自动收集,这个方法也就是接收并存储外部配置好的SecurityFilterChain
列表然后通过这个方法过滤器被添加,通过
webSecurity.addSecurityFilterChainBuilder(...)
方法添加到WebSecurity
的securityFilterChainBuilders
列表中(对应WebSecurity
源码中的securityFilterChainBuilders
集合)。最后,当 Spring 容器初始化时,会调用
WebSecurity
的build()
方法(继承自AbstractSecurityBuilder
),最终执行performBuild()
方法,创建FilterChainProxy
并作为@Bean
注册到 Spring 容器中。而 webSecurity 和httpSecurity 也是同一个父类,因此 webSecurity 的 build 方法也是同样的逻辑至此,FilterChainsProxy也创建完毕了。
最后,FilterChainProxy
作为 Spring 管理的
Filter
类型 Bean,会被 Spring 的
DelegatingFilterProxy
代理,并注册到 Servlet 容器(如
Tomcat)的过滤器链中。
流程如下:
Spring 容器启动时,
DelegatingFilterProxy
作为 Servlet 过滤器被注册(通过AbstractSecurityWebApplicationInitializer
自动配置)。DelegatingFilterProxy
会从 Spring 容器中查找名为springSecurityFilterChain
的Filter
Bean(默认就是WebSecurity
构建的FilterChainProxy
)。当请求到达 Servlet 容器时,会先经过
DelegatingFilterProxy
,再转发给FilterChainProxy
执行实际的安全过滤逻辑。
然后我们就进行梳理HttpSecurity
初始化
SecurityFilterChain
过滤器链的流程
当调用 http.build()
(HttpSecurity
继承自
SecurityBuilder
,build
方法用于构建最终的安全组件)时,会触发以下关键步骤来初始化
SecurityFilterChain
:
执行
init()
方法,遍历所有注册到HttpSecurity
的SecurityConfigurer
,调用它们的init
方法,完成配置器的初始化准备。执行
configure()
方法,再次遍历所有SecurityConfigurer
,调用它们的configure
方法。在这个过程中,各个配置器会根据自身的配置逻辑,生成对应的过滤器,并将这些过滤器添加到HttpSecurity
的filters
列表中。例如CsrfConfigurer
会创建CsrfFilter
并添加到filters
;AuthorizeHttpRequestsConfigurer
会创建FilterSecurityInterceptor
来处理授权规则,并添加到filters
。
构建
DefaultSecurityFilterChain
,在HttpSecurity
的performBuild
方法中,会对filters
列表中的过滤器按照预设的顺序(由FilterOrderRegistration
管理)进行排序,然后结合请求匹配器(RequestMatcher
,用于判断哪些请求需要经过该过滤链),创建DefaultSecurityFilterChain
实例注册
SecurityFilterChain
,生成的DefaultSecurityFilterChain
会被注册到FilterChainProxy
中。FilterChainProxy
是 Spring Security 过滤器链的代理,它会根据请求的匹配情况,选择对应的SecurityFilterChain
来处理请求,从而实现对 HTTP 请求的安全拦截与校验。
所以说,HttpSecurity
初始化
SecurityFilterChain
过滤器链的过程,是通过
init()
方法初始化配置器,configure()
方法让配置器生成过滤器,再对过滤器排序并结合请求匹配器构建
DefaultSecurityFilterChain
,最后将其注册到
FilterChainProxy
中,以此来实现对 HTTP 请求的安全过滤。