spring-security 架构-Servlet
- 版本信息
- Java Web Servlet
- servlet 处理 http 请求过程- Tomcat 容器
- Spring Security 过滤器链如何注册?
- DelegatingFilterProxy、FilterChainProxy、SecurityFilterChain
- 执行流程图
SpringBoot web 项目默认使用的是 servlet 处理请求的,本章介绍 spring-security 过滤器链初始化以及执行过程。
版本信息
内容 | 版本 |
---|---|
JDK | 17 |
spring-boot-starter-web | 3.2.2 |
spring-boot-starter-security | 3.2.2 |
spring-security | 6.2.1 |
Java Web Servlet
servlet 处理 http 请求过程- Tomcat 容器
-
根据 url 匹配 使用那个 servlet 处理请求,源码方法
org.apache.catalina.mapper.Mapper#internalMapWrapper
,具体内容参考博客https://blog.csdn.net/m0_52440465/article/details/122766656。SpringBoot 项目如果未配置Servlet,一般会匹配到 DispatcherServlet (Spring MVC) -
创建过滤器链,方法
org.apache.catalina.core.StandardWrapperValve#invoke
根据请求url 匹配需要执行的过滤器
3. 执行过滤器方法,在执行Spring Security 过滤器的时候,第一次请求会在Spring 容器中查找对应的过滤器链,注册到 Tomcat 容器中的是 Spring Security 的代理过滤器 DelegatingFilterProxy
4. servlet 处理请求,servlet 处理请求的时候经过若干个拦截器
Spring Security 过滤器链如何注册?
-
DelegatingFilterProxyRegistrationBean
设置目标 Bean 的名字为springSecurityFilterChain
,在执行过滤器链的时候,会根据这个名字在Spring容器中查找对用的Spring Security过滤器链
将 DelegatingFilterProxyRegistrationBean 加载到服务上下文
org.springframework.boot.web.servlet.ServletContextInitializerBeans#addServletContextInitializerBean(java.lang.String, org.springframework.boot.web.servlet.ServletContextInitializer, org.springframework.beans.factory.ListableBeanFactory)
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#selfInitialize
获取DelegatingFilterProxy
实例,添加到应用上下文
org.springframework.boot.web.servlet.AbstractFilterRegistrationBean#addRegistration
创建DelegatingFilterProxy
实例, 方法org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean#getFilter
注册到Tomcat 容器中
org.apache.catalina.core.ApplicationFilterRegistration#addMappingForUrlPatterns
-
生成默认的过滤器链,
DefaultSecurityFilterChain
,boot 自动装载构建
org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration.SecurityFilterChainConfiguration#defaultSecurityFilterChain
在org.springframework.security.config.annotation.web.builders.HttpSecurity#performBuild
方法中生成的默认过滤器链DefaultSecurityFilterChain
-
创建过滤器链代理类
FilterChainProxy
,Bean 的名字为springSecurityFilterChain
, 注意,这里生成Bean的名字和第一步DelegatingFilterProxy
目标Bean 的名字是一致的
从这个Bean 的创建代码,可以看出,一个Bean可以支持多个SecurityFilterChain
过滤器链的配置 -
构建过滤器链代理类
FilterChainProxy
,webSecurity.build()
方法会调用父类的org.springframework.security.config.annotation.web.builders.WebSecurity#performBuild
方法,过滤器链代理类生成的代码片段如下
DelegatingFilterProxy、FilterChainProxy、SecurityFilterChain
图片来源于官网 https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-delegatingfilterproxy
DelegatingFilterProxy
委托代理过滤器类,服务启动初始化的时候会注册到Tomcat容器中。在http请求到达服务器,执行过滤器链方法的时候,根据目标Bean的名字springSecurityFilterChain
,在 Spring容器查找对应的Bean代理过滤器FilterChainProxy
。代理过滤器会根据请求匹配到SecurityFilterChain
过滤器链,然后执行对应的过滤器方法。
执行流程图
- 创建过滤器链,调用的方法
org.apache.catalina.core.StandardWrapperValve#invoke
, 执行创建过滤器链方法org.apache.catalina.core.ApplicationFilterFactory#createFilterChain
DelegatingFilterProxy
执行doFilter逻辑,先判断是否初始化了目标过滤器,如果没有的,在Spring容器中,根据目标Bean的名字查找过滤器
FilterChainProxy
代理过滤器类,执行过滤器方法的时候,会根据请求匹配对应的Spring Security 过滤器链。org.springframework.security.web.FilterChainProxy#doFilterInternal
org.springframework.security.web.FilterChainProxy#getFilters(jakarta.servlet.http.HttpServletRequest)
匹配过滤器链,获取将要执行的过滤器列表
- 执行过滤器方法,获取到过滤器列表之后,会构造一个虚拟过滤器链
org.springframework.security.web.FilterChainProxy.VirtualFilterChainDecorator#decorate(jakarta.servlet.FilterChain, java.util.List<jakarta.servlet.Filter>)
执行过滤器逻辑org.springframework.security.web.FilterChainProxy.VirtualFilterChain#doFilter