本章介绍 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

org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
@Import 导入 org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
@EnableWebSecurity
@Import 导入 org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration
HttpSecurityConfiguration 配置类中开始创建 HttpSecurity 的bean 对象
org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder#add 方法中加个断点,看初始化添加了多少个配置类
org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration#applyDefaultConfigurers
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 之后的过滤器才会捕获到异常,并进行异常处理。默认过滤器的顺序如图所示,在 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 中,可以参考如下代码

配置自定义过滤器到过滤器链
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilterBefore(new TenantFilter(), AuthorizationFilter.class);
return http.build();
}
}