• spring-security 过滤器


    本章介绍 spring-security 过滤器配置HttpSecurity,过滤器加载过程,自定义过滤器

    版本信息

    内容版本
    JDK17
    spring-boot-starter-web3.2.2
    spring-boot-starter-security3.2.2
    spring-security6.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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    过滤器加载过程

    创建 HttpSecurity Bean 对象

    1. SpringBoot 自动装载类 org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
      在这里插入图片描述
    2. @Import 导入 org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
      在这里插入图片描述
    3. Spring Security 核心注解类 @EnableWebSecurity
      在这里插入图片描述
    4. @Import 导入 org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration
      在这里插入图片描述
    5. HttpSecurityConfiguration 配置类中开始创建 HttpSecurity 的bean 对象
      在这里插入图片描述
      可以在 org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder#add 方法中加个断点,看初始化添加了多少个配置类
      在这里插入图片描述
      配置类还可以扩展的,基于SPI扩展 org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration#applyDefaultConfigurers
      在这里插入图片描述
      从这段代码可以看出,可以自定义过滤器的配置类,对扩展开放√

    创建过滤器

    1. Spring Boot 自动装载在之前已分析,直接定位到 org.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration, 在这个类中有创建过滤器链的Bean
      在这里插入图片描述
    2. 默认过滤器链编译过程,查看 http.build() 方法
      在这里插入图片描述
      首先判断是否已经构建了,防止重复构建。再执行 doBuild() 方法
      在这里插入图片描述
      在编译的过程中,会读取之前的配置类,将相关的过滤器添加到过滤器链,查看 configure() 方法
      在这里插入图片描述
    3. 在配置类中,创建过滤器类,将过滤器类加载到过滤器链,列举一个配置类org.springframework.security.config.annotation.web.configurers.CsrfConfigurer#configure,其它的配置类和这个相似
      在这里插入图片描述
      将过滤器添加到列表 org.springframework.security.config.annotation.web.builders.HttpSecurity#filters
      在这里插入图片描述
    4. 构建过滤器链,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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    避免过滤器注册到 Tomcat 中,可以参考如下代码
    在这里插入图片描述
    配置自定义过滤器到过滤器链

    @Configuration
    public class SecurityConfig {
    
        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http.addFilterBefore(new TenantFilter(), AuthorizationFilter.class);
            return http.build();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    个人用户如何保证企业邮箱安全?【网易企业邮箱】
    【第54篇】知识蒸馏:Distilling the Knowledge in a Neural Network
    Biwen.QuickApi代码生成器功能上线
    Java9新增特性
    webpack分环境打包(生产/开发两套打包)
    【shell】read -t -n1
    spring cloud 快速上手系列 -> 03-消息队列 Stream -> 032-使用spring cloud bus实现配置中心热刷新-Server
    Kuboard突然无法访问提示:Failed to connect to the database
    stl 容器内存
    Android音视频开发:MediaCodec解码视频,得到YUV值,一帧一帧加载到SD卡中保存
  • 原文地址:https://blog.csdn.net/modelmd/article/details/136178028