未央一梦
1.21GB · 2025-09-15
属于 Spring Web(Servlet 规范 + Spring Framework) 的类,不是 Spring Security 专属, 它是连接 Servlet 容器中的 Filter 与 Spring 容器中的 Bean 的关键桥梁。
它本身是一个标准的 jakarta.servlet.Filter
,但是并不直接做实际的过滤逻辑,而是 把请求委托给 Spring 容器里定义的某个 Bean(通常是一个 Filter 类型的 Bean) 去执行(如 FilterChainProxy
)去执行。
web.xml
(或 ServletContext
注册的 Filter),只能直接加载类实例,无法感知 Spring 容器里的 Bean。DelegatingFilterProxy
作为适配器,把 Servlet 容器里的 Filter 请求转发给 Spring 容器里的目标 Bean。简单说:
Tomcat → 调用 DelegatingFilterProxy
→ 找到 Spring 容器中的 bean → 委托执行。
Servlet 容器启动时,DelegatingFilterProxy
被注册为 Filter。
它会从 Spring 容器里找到与自己名字(或配置的名字)相同的 Bean(通常是 FilterChainProxy
)。
每次请求进来时:
DelegatingFilterProxy#doFilter(...)
会调用目标 Bean 的 doFilter(...)
。public class DelegatingFilterProxy extends GenericFilterBean {
private String targetBeanName;
private WebApplicationContext webApplicationContext;
private volatile Filter delegate;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 初始化目标 Bean(只做一次)initFilterBean -> this.delegate = this.initDelegate(wac);
Filter delegateToUse = this.delegate;
// 委托目标 Bean 执行过滤逻辑
delegateToUse.doFilter(request, response, filterChain);
}
}
角色:Spring Security 的核心入口 Filter。
职责:
DelegatingFilterProxy
转发)。DelegatingFilterProxy
。Filter delegate = getDelegate(); // 获取 springSecurityFilterChain Bean
delegate.doFilter(request, response, filterChain);
delegate
就是 FilterChainProxy
实例。
所以 FilterChainProxy#doFilter()
被 Servlet 容器调用,传入原始 FilterChain
(继续调用 DispatcherServlet 或下一个 Filter)。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);
HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse) response);
// 找到匹配的 SecurityFilterChain
List<Filter> filters = null;
// 多条 SecurityFilterChain 如何匹配
for (SecurityFilterChain chain : this.filterChains) {
if (chain.matches(request)) {
// 默认只执行第一个匹配的; 所以在配置多个链时,顺序很重要,URL 模式越具体的链应该放前面。
filters = chain.getFilters();
break;
}
}
// 没匹配到 -> 直接放行
if (filters == null || filters.size() == 0) {
this.filterChainDecorator.decorate(chain).doFilter(firewallRequest, firewallResponse);
return;
}
// 如果匹配:
// 创建“重置链”,用于恢复请求状态并调用原始 FilterChain
FilterChain reset = (req, res) -> {
// 恢复请求状态,清理 Security Filter 改动。
firewallRequest.reset();
chain.doFilter(req, res); // 调用原始 FilterChain, 其实就是 Servlet 容器原本的 FilterChain(最终会到 DispatcherServlet)。
};
// 创建 VirtualFilterChain,执行 Filters, 最后调用 reset
this.filterChainDecorator.decorate(reset, filters).doFilter(firewallRequest, firewallResponse);
}
SecurityFilterChain
是一个接口,包含一组 Spring Security 的内置 Filter 和 对应一个 URL 配置模式。public interface SecurityFilterChain {
boolean matches(HttpServletRequest request);
List<Filter> getFilters();
}
RequestMatcher
判断请求是否匹配, 找到第一个匹配的链执行。
matches()
通常是 DefaultSecurityFilterChain
实现,内部使用 RequestMatcher
判断 URL 是否匹配:public boolean matches(HttpServletRequest request) {
return this.requestMatcher.matches(request);
}
可以有多个 SecurityFilterChain
(多安全配置),比如:
/api/**
→ JWT 认证的过滤器链/admin/**
→ Session 登录的过滤器链private static class VirtualFilterChain implements FilterChain {
private final FilterChain originalChain;// FilterChain resert
private final List<Filter> additionalFilters; // 这一条 SecurityFilterChain 内的所有 Security Filter
private final int size; // Filter 数量
private int currentPosition = 0; // 当前执行到第几个 Filter
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
// 递归终止条件:如果已经执行完 additionalFilters 中的所有 Filter,调用 原始 FilterChain
// 保证请求最终能到 DispatcherServlet 或原始 Filter 链。
if (currentPosition == additionalFilters.size()) {
// 所有 Security Filter 执行完后 -> 继续执行原始 FilterChain,保证请求最终能到达 DispatcherServlet。
originalChain.doFilter(request, response);
return;
}
this.currentPosition++;
// 取出当前 Filter
Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
// 调用它的 doFilter, 把 VirtualFilterChain 自身 (this) 作为下一个 FilterChain 传入
nextFilter.doFilter(request, response, this); // 递归
}
}
顺序执行
additionalFilters
列表的顺序。AuthenticationException
),会被 ExceptionTranslationFilter
捕获处理,不会继续执行后续 Filter。递归链
chain.doFilter()
,进入下一层 Filter。最终回原始链
currentPosition == size
,执行 originalChain.doFilter()
,把请求交回原始的 Servlet FilterChain(进入 DispatcherServlet)。springSecurityFilterChain
的 Bean(即 FilterChainProxy
)。FilterChainProxy
注册为一个 名为 "springSecurityFilterChain" 的 Bean。@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// HttpSecurity DSL 配置生成 SecurityFilterChain
return http.build();
}
}
底层过程:
@EnableWebSecurity
会触发 WebSecurityConfiguration
自动配置,注册 springSecurityFilterChain
BeanFilterChainProxy
@Bean(name = "springSecurityFilterChain")
public FilterChainProxy springSecurityFilterChain(List<SecurityFilterChain> chains) {
return new FilterChainProxy(chains);
}
假设你在 web.xml
或 Spring Boot 默认注册了(一般就自动配置):
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Tomcat / Servlet 容器启动:
DelegatingFilterProxy
DelegatingFilterProxy.init()
@Override
public void init(FilterConfig filterConfig) {
// 1. Bean 名称,默认为 filter-name
String targetBeanName = getTargetBeanName();
// 2. 从 Spring WebApplicationContext 获取 Bean
this.delegate = obtainWebApplicationContext(filterConfig)
.getBean(targetBeanName, Filter.class);
// delegate 就是 FilterChainProxy 实例
}
delegate
就是 FilterChainProxy Bean@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws ServletException, IOException {
this.delegate.doFilter(request, response, chain); // ✅ 这里调用 FilterChainProxy.doFilter()
}
┌───────────────────────────────┐
│ 客户端请求 │
└───────────────┬───────────────┘
│
▼
Tomcat / Servlet 容器 Filter 链
│
▼
┌───────────────────────────────┐
│ DelegatingFilterProxy (Filter) │
│ init(): 获取 delegate Bean │
│ delegate = springSecurityFilterChain (FilterChainProxy) │
└───────────────┬───────────────┘
│ doFilter(request, response, chain)
▼
┌─────────────────────────┐
│ FilterChainProxy │
│ doFilterInternal(): │
│ 1️⃣ Firewall 防护 │
│ 2️⃣ 匹配 SecurityFilterChain │
│ 3️⃣ 创建 VirtualFilterChain │
│ 4️⃣ 执行 Security Filter 链 │
└───────────────┬─────────┘
│
▼
┌─────────────────────────┐
│ VirtualFilterChain │
│(递归执行每个 Filter) │
│ ┌───────────────┐ │
│ │ SecurityFilter1│ --> chain.doFilter(this)
│ ├───────────────┤
│ │ SecurityFilter2│ --> chain.doFilter(this)
│ └───────────────┘
│
│ 当 currentPosition == size
│ 执行 reset 链
▼
┌───────────────────────────────┐
│ FilterChain reset (lambda) │
│ firewallRequest.reset() │
│ originalChain.doFilter() │ <-- 调用原始 FilterChain
└───────────────┬───────────────┘
│
▼
┌──────────────────────────┐
│ DispatcherServlet / MVC │
│ Controller 业务处理 │
└──────────────────────────┘
reset 链
reset
链就是保证 请求能回到原始处理链SecurityFilterChain
original FilterChain / DispatcherServlet