为什么引入springsecurity的依赖后,会自动创建了过滤器链

spring.factories.imports 文件

在 Spring Boot 2.7 之前,自动配置类的注册是通过 META-INF/spring.factories 文件完成的,其中包含类似这样的条目:

为了提高性能、模块化和可读性,Spring Boot 2.7 引入了新的、专用的 .imports 文件机制来替代 spring.factories 中的自动配置注册。

org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件是一个纯文本文件,每行包含一个自动配置类的全限定类名(Fully Qualified Class Name)

  • 每行一个类名
  • 支持注释 :以 # 开头的行被视为注释,可以用来说明或临时禁用某个配置。
  • 语义清晰:文件名本身就说明了它的用途------注册自动配置导入。

工作原理

  1. 启动扫描 :当你的 Spring Boot 应用程序启动时,SpringApplication 会扫描所有 classpath 下的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件。
  2. 读取类名:它会读取这些文件中的每一行,获取自动配置类的全限定名。
  3. 条件化加载 :对于每个列出的类,Spring Boot 会检查其上的条件注解(如 @ConditionalOnClass, @ConditionalOnMissingBean, @ConditionalOnProperty 等)。
  4. 注册 Bean :如果所有条件都满足,该自动配置类就会被加载,其中定义的 @Bean 方法会被执行,相关的组件(如数据源、模板引擎、安全配置等)就会自动注册到 Spring 应用上下文中。

SecurityAutoConfiguration

当我们引入了security相关依赖的时候,SecurityAutoConfiguration自动配置类开始发挥作用

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
ruby 复制代码
@Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {

}

SecurityAutoConfiguration中引入了SpringBootWebSecurityConfiguration配置类

less 复制代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {

  
   @Configuration(proxyBeanMethods = false)
   @ConditionalOnDefaultWebSecurity
   static class SecurityFilterChainConfiguration {
        
      //配置默认的过滤器链条  
      @Bean
      @Order(SecurityProperties.BASIC_AUTH_ORDER)
      SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
         http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
         http.formLogin(withDefaults());
         http.httpBasic(withDefaults());
         return http.build();
      }

   }

   // 启用@EnableWebSecurity注解
   @Configuration(proxyBeanMethods = false)
   @ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
   @ConditionalOnClass(EnableWebSecurity.class)
   @EnableWebSecurity
   static class WebSecurityEnablerConfiguration {

   }

}

SpringBootWebSecurityConfiguration做了两件事相对重要 一是创建了默认的过滤器链,二是使用了@EnableWebSecurity注解 这就是为什么我们只引入了jar包 springsecurity就可以通过默认的过滤器链来保护我们的资源,同时我们也可以看出开发者如果忘记了使用@EnableWebSecurity注解也没关系,框架会自动帮我们开启。

默认过滤器链

从上面的代码我们可以看出 SecurityFilterChainConfiguration将SecurityFilterChain实例注入到容器中,但前提是@ConditionalOnDefaultWebSecurity这个注解需要生效

css 复制代码
@ConditionalOnDefaultWebSecurity

@ConditionalOnDefaultWebSecurity本质上是@Conditional注解

less 复制代码
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(DefaultWebSecurityCondition.class)
public @interface ConditionalOnDefaultWebSecurity {

}

@Conditional(DefaultWebSecurityCondition.class) 这个是spring的条件化配置,意思是只有当 DefaultWebSecurityCondition 这个条件被判定为 true 时,被它标注的类或方法才应该被注册到 Spring 容器中(即生效);否则,就跳过它。

@Conditional注解要求传入一个实现了Condition接口的类作为参数,DefaultWebSecurityCondition实现了这个接口

  • 在 Spring 应用上下文启动过程中,当遇到被 @Conditional 标注的元素时,Spring 会实例化你指定的 Condition 类(这里是 DefaultWebSecurityCondition),并调用其 matches() 方法。
java 复制代码
@FunctionalInterface
public interface Condition {
   boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}

这个类的主要作用是: 当内部类的所有的 .@Conditional 注解都成立的时候,才会注入该 Bean

scala 复制代码
class DefaultWebSecurityCondition extends AllNestedConditions {

   DefaultWebSecurityCondition() {
      super(ConfigurationPhase.REGISTER_BEAN);
   }

   //  **作用**:`@ConditionalOnClass` 注解检查类路径(classpath)上是否存在指定的类。
   //**逻辑**:只有当 `SecurityFilterChain.class` 和 `HttpSecurity.class` 这两个类**都存在于**类路径上时,这个条件才算通过
   @ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })
   static class Classes {

   }

   // 只有当当前 Spring 容器中**没有**类型为 `SecurityFilterChain` 的 Bean 时,这个条件才算通过
   @ConditionalOnMissingBean({ SecurityFilterChain.class })
   static class Beans {

   }

}

所以springsecurity自动创建过滤器链的满足的条件是:1 类需要存在 2.用户没有手动的配置SecurityFilterChain。

目的 :这是实现"自定义优先 "(Opinionated Defaults)的关键。Spring Boot 的理念是,如果开发者没有进行任何安全配置,它就提供一个安全的默认配置(通常是一个简单的登录表单)。但如果开发者自己定义了一个 SecurityFilterChain Bean 来配置自定义的安全规则(比如 OAuth2、JWT、特定的 URL 权限等),那么 Spring Boot 就应该自动禁用 其默认的安全配置,避免冲突。这个条件确保了只有在用户没有提供自己的安全配置时,才会应用默认配置

EnableWebSecurity

上面说自动配置类WebSecurityEnablerConfiguration帮我开启EnableWebSecurity注解, 但是有个前提是

@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN) @ConditionalOnClass(EnableWebSecurity.class) 这两个条件得同时生效 1是类路径中要存在EnableWebSecurity这个类 2是** Spring 容器中不存在名为 "springSecurityFilterChain" 的 Bean**

这么做的目的是:当 @EnableWebSecurity 注解被处理时,它会创建一个名为 springSecurityFilterChainFilterChainProxy Bean,这个 Bean 是整个 Spring Security 过滤器链的入口,如果用户正确地使用了 @EnableWebSecurity @EnableWebSecurity 注解本身就会触发创建 springSecurityFilterChain Bean。 同样,WebSecurityEnablerConfiguration 会因为该 Bean 已存在而被禁用,防止了 @EnableWebSecurity 被应用两次。

相关推荐
catchadmin1 小时前
PHP 快速集成 ChatGPT 用 AI 让你的应用更聪明
人工智能·后端·chatgpt·php
whltaoin5 小时前
SpringCloud 项目阶段九:Kafka 接入实战指南 —— 从基础概念、安装配置到 Spring Boot 实战及高可用设计
spring boot·spring cloud·kafka
callJJ5 小时前
从 0 开始理解 Spring 的核心思想 —— IoC 和 DI(2)
java·开发语言·后端·spring·ioc·di
不务专业的程序员--阿飞7 小时前
JVM无法分配内存
java·jvm·spring boot
你的人类朋友7 小时前
JWT的组成
后端
Q_Q5110082858 小时前
python+django/flask+uniapp基于微信小程序的瑜伽体验课预约系统
spring boot·python·django·flask·uni-app·node.js·php
北风朝向8 小时前
Spring Boot参数校验8大坑与生产级避坑指南
java·spring boot·后端·spring
canonical_entropy9 小时前
一份关于“可逆计算”的认知解码:从技术细节到哲学思辨的完整指南
后端·低代码·deepseek
Gobysec9 小时前
Goby 漏洞安全通告|Spring Cloud Gateway 信息泄露漏洞(CVE-2025-41243)
spring boot·安全·cve-2025-41243
趙卋傑9 小时前
项目发布部署
linux·服务器·后端·web