• SpringSecurity系列一:01 SpringSecurity 的自动配置原理


    1. 导入 SpringSecurity 依赖

    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-securityartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. SpringBoot 的自动配置功能

    使用Spring Boot时,我们只需引入对应的Starters,Spring Boot启动时便会自动加载相关依赖,配置相应的初始化参数,以最快捷、简单的形式对第三方软件进行集成,这便是Spring Boot的自动配置功能。

    在这里插入图片描述

    可以用一句话来描述整个过程:Spring Boot通过@EnableAutoConfiguration注解开启自动配置,加载spring.factories中注册的各种AutoConfiguration类,当某个AutoConfiguration类满足其注解@Conditional指定的生效条件(Starters提供的依赖、配置或Spring容器中是否存在某个Bean等)时,实例化该AutoConfiguration类中定义的Bean(组件等),并注入Spring容器,就可以完成依赖框架的自动配置。

    • @EnableAutoConfiguration:该注解由组合注解@SpringBootApplication引入,完成自动配置开启,扫描各个jar包下的spring.factories文件,并加载文件中注册的AutoConfiguration类等。
    • spring.factories:配置文件,位于jar包的META-INF目录下,按照指定格式注册了自动配置的AutoConfiguration类。spring.factories也可以包含其他类型待注册的类。该配置文件不仅存在于Spring Boot项目中,也可以存在于自定义的自动配置(或Starter)项目中。
    • AutoConfiguration类:自动配置类,代表了Spring Boot中一类以XXAutoConfiguration命名的自动配置类。其中定义了三方组件集成Spring所需初始化的Bean和条件。
    • @Conditional:条件注解及其衍生注解,在AutoConfiguration类上使用,当满足该条件注解时才会实例化AutoConfiguration类。
    • Starters:三方组件的依赖及配置,Spring Boot已经预置的组件。Spring Boot默认的Starters项目往往只包含了一个pom依赖的项目。如果是自定义的starter,该项目还需包含spring.factories文件、AutoConfiguration类和其他配置类。

    1. 入口类和 @SpringBootApplication 注解

    @EnableAutoConfiguration是开启自动配置的注解,在创建的Spring Boot项目中并不能直接看到此注解,它是由组合注解@SpringBootApplication引入的。

    Spring Boot项目创建完成会默认生成一个*Application的入口类。通过该类的main方法即可启动Spring Boot项目。

    @SpringBootApplication
    public class SpringSecurity01Application {
        public static void main(String[] args) {
            SpringApplication.run(SpringSecurity01Application.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在Spring Boot入口类(除单元测试外)中,唯一的一个注解就是@SpringBootApp-lication。它是Spring Boot项目的核心注解,用于开启自动配置,准确说是通过该注解内组合的@EnableAutoConfiguration开启了自动配置。

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    
    	/**
    	 * Exclude specific auto-configuration classes such that they will never be applied.
    	 * 排除指定的自动配置类
    	 */
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	Class<?>[] exclude() default {};
    
    	/**
    	 * Exclude specific auto-configuration class names such that they will never be
    	 * applied.
    	 * 排除指定自动配置类名 
    	 */
    	@AliasFor(annotation = EnableAutoConfiguration.class)
    	String[] excludeName() default {};
    
    	/**
    	 * Base packages to scan for annotated components. 
    	 * 指定扫描的基础包,激活注解组件的初始化
    	 */
    	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    	String[] scanBasePackages() default {};
    
    	/**
    	 * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
    	 * scan for annotated components. The package of each class specified will be scanned.
    	 * 指定扫描的类,用于初始化
    	 */
    	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    	Class<?>[] scanBasePackageClasses() default {};
    
    	@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
    	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
    
    	@AliasFor(annotation = Configuration.class)
    	boolean proxyBeanMethods() default true;
    }
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    ① @SpringBootConfiguration注解源码:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    @Indexed
    public @interface SpringBootConfiguration {
    	@AliasFor(annotation = Configuration.class)
    	boolean proxyBeanMethods() default true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ② @EnableAutoConfiguration注解源码:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    
       /**
        * Environment property that can be used to override when auto-configuration is
        * enabled.
        */
       String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
       /**
        * Exclude specific auto-configuration classes such that they will never be applied.
        */
       Class<?>[] exclude() default {};
    
       /**
        * Exclude specific auto-configuration class names such that they will never be
        * applied.
        */
       String[] excludeName() default {};
    
    }
    
    • 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

    注解中的成员属性:

    • exclude:根据类(Class)排除指定的自动配置,该成员属性覆盖了@SpringBootApplication中组合的@EnableAutoConfiguration中定义的exclude成员属性。

    • excludeName:根据类名排除指定的自动配置,覆盖了@EnableAutoConfiguration中的excludeName的成员属性。

    • scanBasePackages:指定扫描的基础package,用于激活@Component等注解类的初始化。

    • Spring Boot中大量使用了@AliasFor注解,该注解用于桥接到其他注解,该注解的属性中指定了所桥接的注解类。如果点进去查看,会发现@SpringBootApplication定义的属性在其他注解中已经定义过了。之所以使用@AliasFor注解并重新在@SpringBootApplication中定义,更多是为了减少用户使用多注解带来的麻烦。

    @SpringBootApplication注解中组合了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan。因此,在实践过程中也可以使用这3个注解来替代@SpringBootApplication。

    在这里插入图片描述

    2. 注解 @EnableAutoConfiguration功能

    在未使用Spring Boot的情况下,Bean的生命周期由Spring来管理,然而Spring无法自动配置@Configuration注解的类。而Spring Boot的核心功能之一就是根据约定自动管理该注解标注的类。用来实现该功能的组件之一便是@EnableAutoConfiguration注解。

    @EnableAutoConfiguration位于spring-boot-autoconfigure包内,当使用@SpringBootApplication注解时,@EnableAutoConfiguration注解会自动生效。

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    
       /**
        * Environment property that can be used to override when auto-configuration is
        * enabled.
        * 用来覆盖配置开启/关闭自动配置的功能
        */
       String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
       /**
        * Exclude specific auto-configuration classes such that they will never be applied.
        * 根据类排除指定的自动配置
        */
       Class<?>[] exclude() default {};
    
       /**
        * Exclude specific auto-configuration class names such that they will never be
        * applied.
        * 根据类名排除指定的自动配置
        */
       String[] excludeName() default {};
    }
    
    • 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

    @EnableAutoConfiguration注解提供了一个常量和两个成员参数的定义:

    • ENABLED_OVERRIDE_PROPERTY:用来覆盖开启/关闭自动配置的功能;
    • exclude:根据类(Class)排除指定的自动配置;
    • excludeName:根据类名排除指定的自动配置;

    @EnableAutoConfiguration会猜测你需要使用的Bean,但如果在实战中你并不需要它预置初始化的Bean,可通过该注解的exclude或excludeName参数进行有针对性的排除。比如,当不需要数据库的自动配置时:

    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    public class SpringSecurity01Application {
        public static void main(String[] args) {
            SpringApplication.run(SpringSecurity01Application.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3. 条件注解 @Conditional

    @Conditional注解是由Spring 4.0版本引入的新特性,可根据是否满足指定的条件来决定是否进行Bean的实例化及装配,比如,设定当类路径下包含某个jar包的时候才会对注解的类进行实例化操作。总之,就是根据一些特定条件来控制Bean实例化的行为,@Conditional注解代码如下:

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Conditional {
    
       Class<? extends Condition>[] value();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    @Conditional注解唯一的元素属性是接口Condition的数组,只有在数组中指定的所有Condition的matches方法都返回true的情况下,被注解的类才会被加载。

    @FunctionalInterface
    public interface Condition {
       /**
        * Determine if the condition matches.
        */
       boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    matches方法的第一个参数为ConditionContext,可通过该接口提供的方法来获得Spring应用的上下文信息,ConditionContext接口定义如下:

    public interface ConditionContext {
    
       /**
        * Return the {@link BeanDefinitionRegistry} that will hold the bean definition
        * should the condition match.
        * 
        */
       BeanDefinitionRegistry getRegistry();
    
       /**
        * Return the {@link ConfigurableListableBeanFactory} that will hold the bean
        * definition should the condition match, or {@code null} if the bean factory is
        * not available (or not downcastable to {@code ConfigurableListableBeanFactory}).
        */
       @Nullable
       ConfigurableListableBeanFactory getBeanFactory();
    
       /**
        * Return the {@link Environment} for which the current application is running.
        */
       Environment getEnvironment();
    
       /**
        * Return the {@link ResourceLoader} currently being used.
        */
       ResourceLoader getResourceLoader();
    
       /**
        * Return the {@link ClassLoader} that should be used to load additional classes
        * (only {@code null} if even the system ClassLoader isn't accessible).
        */
       @Nullable
       ClassLoader getClassLoader();
    }
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    matches方法的第二个参数为AnnotatedTypeMetadata,该接口提供了访问特定类或方法的注解功能,并且不需要加载类,可以用来检查带有@Bean注解的方法上是否还有其他注解,AnnotatedTypeMetadata接口定义如下:

    public interface AnnotatedTypeMetadata {
    
       MergedAnnotations getAnnotations();
    
       boolean isAnnotated(String annotationName);
    
       @Nullable
       Map<String, Object> getAnnotationAttributes(String annotationName);
    
       @Nullable
       Map<String, Object> getAnnotationAttributes(String annotationName,boolean classValuesAsString) ;
     
       @Nullable
       MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);
     
       @Nullable
       MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    该接口的isAnnotated方法能够提供判断带有@Bean注解的方法上是否还有其他注解的功能。其他方法提供不同形式的获取@Bean注解的方法上其他注解的属性信息。

    在Spring Boot的autoconfigure项目中提供了各类基于@Conditional注解的衍生注解,它们适用不同的场景并提供了不同的功能:

    • @ConditionalOnBean:在容器中有指定Bean的条件下;
    • @ConditionalOnClass:在classpath类路径下有指定类的条件下;
    • @ConditionalOnCloudPlatform:当指定的云平台处于active状态时;
    • @ConditionalOnExpression:基于SpEL表达式的条件判断;
    • @ConditionalOnJava:基于JVM版本作为判断条件;
    • @ConditionalOnMissingBean:当容器里没有指定Bean的条件时;
    • @ConditionalOnMissingClass:当类路径下没有指定类的条件时;
    • @ConditionalOnProperty:在指定的属性有指定值的条件下;
    • @ConditionalOnResource:类路径是否有指定的值;
    • @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个或者有多个但是指定了首选的Bean时;
    • @ConditionalOnWebApplication:在项目是一个Web项目的条件下;

    3. SpringSecurity的自动配置

    1. SecurityAutoConfiguration

    @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
    public class SpringSecurity01Application {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringSecurity01Application.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Spring Boot通过@EnableAutoConfiguration注解开启自动配置,加载spring.factories中注册的各种AutoConfiguration类,当某个AutoConfiguration类满足其注解@Conditional指定的生效条件时,实例化该AutoConfiguration类中定义的Bean,并注入Spring容器,就可以完成依赖框架的自动配置。

    首先,加载org.springframework.boot.autoconfigure包下META-INF/spring.factories中注册的key=org.springframework.boot.autoconfigure.EnableAutoConfigurationvalue=SecurityAutoConfiguration的自动配置类:

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    ...
    org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
    org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    当完成注册之后,在加载的过程中会使用元数据的配置进行过滤,对应的配置内容在META-INF/spring-autoconfigure-metadata.properties文件中:

    org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.ConditionalOnClass=org.springframework.security.authentication.DefaultAuthenticationEventPublisher
    
    • 1

    在过滤的过程中要判断自动配置类SecurityAutoConfiguration是否被@ConditionalOnClass注解,源代码如下:

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
    @EnableConfigurationProperties(SecurityProperties.class)
    @Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
          SecurityDataConfiguration.class, ErrorPageSecurityFilterConfiguration.class })
    public class SecurityAutoConfiguration {
    
       @Bean
       @ConditionalOnMissingBean(AuthenticationEventPublisher.class)
       public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {
          return new DefaultAuthenticationEventPublisher(publisher);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    可以看到,该配置类SecurityAutoConfiguration被@ConditionalOnClass注解,并且指定实例化的条件为类路径下必须有DefaultAuthenticationEventPublisher类存在,如果Spring容器当中没有对应的类,则该类不会被注入。再看一下该类的其他注解:

    • @Configuration:指定该类作为配置项来进行实例化操作;

    • @Import:导入@Configuration注解类,这里导入了SpringBootWebSecurityConfiguration.class,WebSecurityEnablerConfiguration.class,SecurityDataConfiguration.class,ErrorPageSecurityFilterConfiguration.class。

    • @ConditionalOnMissingBean:注释于方法上,与@Bean配合,当Spring容器中没有该Bean的实例化对象时才会进行实例化。即当Spring容器中没有AuthenticationEventPublisher实例时,才会实例化DefaultAuthenticationEventPublisher对象,注入Spring容器。如果有了,那么就会覆盖掉当前默认的。

    • @EnableConfigurationProperties:参数为SecurityProperties.class,开启属性注入,可以通过在application.yaml 文件中配置这个 SecurityProperties 类中的属性。

      @ConfigurationProperties(prefix = "spring.security")
      public class SecurityProperties {
      
         public static final int BASIC_AUTH_ORDER = Ordered.LOWEST_PRECEDENCE - 5;
      
         public static final int IGNORED_ORDER = Ordered.HIGHEST_PRECEDENCE;
      
         public static final int DEFAULT_FILTER_ORDER 
             = OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER - 100;
      
         private final Filter filter = new Filter();
         private final User user = new User();
      
         public static class Filter {
             
            private int order = DEFAULT_FILTER_ORDER;
             
            private Set<DispatcherType> dispatcherTypes = new HashSet<>(
                  Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
         }
      
         public static class User {
            /**
             * Default user name.
             */
            private String name = "user";
      
            /**
             * Password for the default user name.
             */
            private String password = UUID.randomUUID().toString();
      
            /**
             * Granted roles for the default user name.
             */
            private List<String> roles = new ArrayList<>();
      
            private boolean passwordGenerated = true;
         }
      }
      
      • 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
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40

      而在application.properties中,我们会进行如下对应配置,修改默认的用户名和密码:

      spring.security.user.name=root
      spring.security.user.password=root
      spring.security.user.roles=admin,user
      
      • 1
      • 2
      • 3

    2. SpringBootWebSecurityConfiguration

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnDefaultWebSecurity
    @ConditionalOnWebApplication(type = Type.SERVLET)
    class SpringBootWebSecurityConfiguration {
    
       @Bean
       @Order(SecurityProperties.BASIC_AUTH_ORDER)
       SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
          http.authorizeRequests()
               // 对所有的请求开启权限认证,认证之后才能访问
              .anyRequest().authenticated()
              .and()
               // 支持表单认证
              .formLogin()
              .and()
               // 支持basic认证
              .httpBasic();
          return http.build();
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    @Configuration:说明该类SpringBootWebSecurityConfiguration会作为一个配置类的组件注入到Spring容器当中 ,并且不会生成对应的代理;

    该类SpringBootWebSecurityConfiguration注入到Spring容器并实例化需要满足下面两个条件:

    @ConditionalOnWebApplication(type = Type.SERVLET):参数为Type.SERVLET,说明该类只有在基于servlet的Web应用中才会被实例化。SpringBoot 集成了tomcat,默认就是一个servelet项目,因此条件满足。

    @ConditionalOnDefaultWebSecurity:组合了注解@Conditional(DefaultWebSecurityCondition.class),该注解依赖于DefaultWebSecurityCondition类,

    @Target({ ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    // 条件注解,依赖于DefaultWebSecurityCondition类
    @Conditional(DefaultWebSecurityCondition.class)
    public @interface ConditionalOnDefaultWebSecurity {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果@ConditionalOnDefaultWebSecurity 条件成立需要满足下面两个条件:

    @ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class }) :当classpath类路劲下存在SecurityFilterChain.class, HttpSecurity.classs 时,条件成立;

    @ConditionalOnMissingBean({ WebSecurityConfigurerAdapter.class, WebSecurityConfigurerAdapter.class }):当Spring容器中不存在WebSecurityConfigurerAdapter,WebSecurityConfigurerAdapter 实例时,条件成立;

    class DefaultWebSecurityCondition extends AllNestedConditions {
    
       DefaultWebSecurityCondition() {
          super(ConfigurationPhase.REGISTER_BEAN);
       }
    
       // 在classpath类路径下有指定类存在的条件下
       // 在classpath类路径下存在 SecurityFilterChain,HttpSecurity 类时,条件满足
       @ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })
       static class Classes {
    
       }
    
       // 当容器里没有指定Bean的条件时
       // Spring的容器中不存在 WebSecurityConfigurerAdapter,SecurityFilterChain 实例时,条件满足
       // 如果Spring容器中存在WebSecurityConfigurerAdapter, SecurityFilterChain,说明我们对WebSecurityConfigurerAdapter, SecurityFilterChain进行了自定义,那么该条件不满足,Spring容器将不会实例化 DefaultWebSecurityCondition
       @ConditionalOnMissingBean({ WebSecurityConfigurerAdapter.class, SecurityFilterChain.class })
       static class Beans {
    
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    当Spring容器中含有 WebSecurityConfigurerAdapter 类及其子类时
    ,那么这个默认的 DefaultWebSecurityCondition 将不会进行配置了,所以这也就是为什么我们对SpringSecurity进行扩展的时候,需要继承 WebSecurityConfigurerAdapter 类来达成自定义配置了。

    3. 总结

    经过上面的分析可以看出,默认情况下,条件都是满足的。SpringSecurity 默认生效的是配置:

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnDefaultWebSecurity
    @ConditionalOnWebApplication(type = Type.SERVLET)
    class SpringBootWebSecurityConfiguration {
    
       @Bean
       @Order(SecurityProperties.BASIC_AUTH_ORDER)
       SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
          http.authorizeRequests()
               // 对所有的请求开启权限认证,认证之后才能访问
              .anyRequest().authenticated()
              .and()
               // 支持表单认证
              .formLogin()
              .and()
               // 支持basic认证
              .httpBasic();
          return http.build();
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    WebSecurityConfigurerAdapter 这个类极其重要,Spring Security 核心配置都在这个类中,
    如果想要扩展SpringSecurity的相关配置,可以在项目中自定义配置类继承WebSecurityConfigurerAdapter类或者实现SecurityFilterChain接口,这样操作都会覆盖掉上面的默认配置,SpringBoot 将所有的扩展配置都放在了WebSecurityConfigurerAdapter和SecurityFilterChain中。如果改配置可以扩展WebSecurityConfigurerAdapter,如果自定义过滤器可以扩展SecurityFilterChain。

    如果要对 Spring Security 进行自定义配置,就要自定义这个类实例,通过覆盖类中方
    法达到修改默认配置的目的:
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    C++数据结构X篇_19_排序基本概念及冒泡排序(重点是核心代码,冒泡是稳定的排序)
    安装内核切换内核
    如何查看IDEA打开的当前项目有多少行代码
    Kubernetes学习(一)入门及集群搭建
    如何从800万数据中快速捞出自己想要的数据?
    security实战
    mysql函数
    必知必会的PyCharm使用技巧
    java多线程下LongAdder、CountDownLatch、CyclicBarrier、Phaser 的用法
    ubuntu安装freeradius3, freeradius3-mysql并配置
  • 原文地址:https://blog.csdn.net/qq_42764468/article/details/126775435