spring-security过滤器
- 版本信息
- 过滤器配置
- 过滤器配置相关类图
- 过滤器加载过程
- 创建 HttpSecurity Bean 对象
- 创建过滤器
- 过滤器作用
- ExceptionTranslationFilter
- 自定义过滤器
本章介绍 spring-security 过滤器配置类
HttpSecurity
,过滤器加载过程,自定义过滤器
版本信息
内容 | 版本 |
---|---|
JDK | 17 |
spring-boot-starter-web | 3.2.2 |
spring-boot-starter-security | 3.2.2 |
spring-security | 6.2.1 |
过滤器配置
过滤器配置相关类图
过滤器链由HttpSecurity
的配置类配置生成的,在HttpSecurity.build()
的时候添加至过滤器链,主要的配置类如下
org.springframework.security.config.annotation.web.configurers.CsrfConfigurer
org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer
org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer
org.springframework.security.config.annotation.web.configurers.SecurityContextConfigurer
org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer
org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer
org.springframework.security.config.annotation.web.configurers.ServletApiConfigurer
org.springframework.security.config.annotation.web.configurers.LogoutConfigurer
org.springframework.security.config.annotation.web.configurers.CorsConfigurer
过滤器加载过程
创建 HttpSecurity Bean 对象
- SpringBoot 自动装载类
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
@Import
导入org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
- Spring Security 核心注解类
@EnableWebSecurity
@Import
导入org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration
- 在
HttpSecurityConfiguration
配置类中开始创建HttpSecurity
的bean 对象
可以在org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder#add
方法中加个断点,看初始化添加了多少个配置类
配置类还可以扩展的,基于SPI扩展org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration#applyDefaultConfigurers
从这段代码可以看出,可以自定义过滤器的配置类,对扩展开放√
创建过滤器
- Spring Boot 自动装载在之前已分析,直接定位到
org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
, 在这个类中有创建过滤器链的Bean
- 默认过滤器链编译过程,查看
http.build()
方法
首先判断是否已经构建了,防止重复构建。再执行doBuild()
方法
在编译的过程中,会读取之前的配置类,将相关的过滤器添加到过滤器链,查看configure()
方法
- 在配置类中,创建过滤器类,将过滤器类加载到过滤器链,列举一个配置类
org.springframework.security.config.annotation.web.configurers.CsrfConfigurer#configure
,其它的配置类和这个相似
将过滤器添加到列表org.springframework.security.config.annotation.web.builders.HttpSecurity#filters
- 构建过滤器链,
org.springframework.security.config.annotation.web.builders.HttpSecurity#performBuild
过滤器作用
ExceptionTranslationFilter
官网介绍 https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-exceptiontranslationfilter
注意,执行顺序在 ExceptionTranslationFilter
之后的过滤器才会捕获到异常,并进行异常处理。默认过滤器的顺序如图所示,在 ExceptionTranslationFilter
之后的过滤器只有 org.springframework.security.web.access.intercept.AuthorizationFilter
,该过滤器抛出的异常可以被异常过滤器捕获到
自定义过滤器
参考官网 https://docs.spring.io/spring-security/reference/servlet/architecture.html#adding-custom-filter,提示部分的内容挺好的
根据提示可以定义过滤器代码如下
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
public class TenantFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String tenantId = request.getHeader("X-Tenant-Id");
boolean hasAccess = isUserAllowed(tenantId);
if (hasAccess) {
filterChain.doFilter(request, response);
return;
}
throw new AccessDeniedException("Access denied");
}
private boolean isUserAllowed(String tenantId) {
// TODO check
return false;
}
}
避免过滤器注册到 Tomcat 中,可以参考如下代码