Default Spring Security rough start process source code analysis

Default Spring Security rough start process source code analysis

Understand the basic process

understand firstspring.factories

spring.factories

org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
  1. SecurityAutoConfiguration is the main configuration class, we mainly explain this class
  2. UserDetailsServiceAutoConfiguration is used to set the default password, which will be configured when SecurityAutoConfiguration configures HttpSecurity, so we won't go into details
  3. SecurityFilterAutoConfiguration does not speak
  4. The latter two are OAuth security, not to mention

We mainly analyze SecurityAutoConfigurationthat it is an automatic configuration class, affected by it EnableWebSecurit , it will be imported HttpSecurityConfigurationand loaded before loadingWebSecurityConfiguration

Their order of action is: HttpSecurityConfigurationconfiguration HttpSecurityConfiguration, WebSecurityConfigurationconfigurationWebSecurity

The process is also mainly around: configuration HttpSecurity--> configure the default basic SecurityFilterChain --> configure WebSecurity--> configure the finalSecurityFilterChain

It can also be understood as: how to create the final one SecurityFilterChain?

EnableWebSecurity and EnableGlobalAuthentication annotations

@Import({
    
     WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class,
      HttpSecurityConfiguration.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
    
    }
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {
    
    }

configurationHttpSecurity

From HttpSecurityConfigurationthe beginning, this class is the basic configuration class of HttpSecurity, the configuration is as follows:

HttpSecurityConfiguration.java

@Autowired
void setAuthenticationConfiguration(AuthenticationConfiguration authenticationConfiguration) {
    
    
    this.authenticationConfiguration = authenticationConfiguration;
}//1
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
HttpSecurity httpSecurity() throws Exception {
    
    
   WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
         this.context);//2
   AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
         this.objectPostProcessor, passwordEncoder);//3
   authenticationBuilder.parentAuthenticationManager(authenticationManager());//4
   HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());//5
   http
      .csrf(withDefaults())
      .addFilter(new WebAsyncManagerIntegrationFilter())
      .exceptionHandling(withDefaults())
      .headers(withDefaults())
      .sessionManagement(withDefaults())
      .securityContext(withDefaults())
      .requestCache(withDefaults())
      .anonymous(withDefaults())
      .servletApi(withDefaults())
      .apply(new DefaultLoginPageConfigurer<>());
   http.logout(withDefaults());//6
   return http;
}
  1. Dependency injection of an AuthenticationConfiguration, pre-loading the AuthenticationConfiguration that needs to be automatically configured earlier,

    This class creates three important Bean objects AuthenticationManagerBuild, InitializeUserDetailsBeanManagerConfigurer and InitializeAuthenticationProviderBeanManagerConfigurer

    used respectively

    • Build the AuthenticationManager
    • Used to initialize UserDetailsServiceAutoConfiguration in spring.factories, its function is to provide default username and password,
    • Initialize the user authentication manager (ProviderManager)
  2. Create a lazy password loader

  3. Create an authentication manager builder

  4. Build an authentication manager

    AuthenticationConfiguration.java

    public AuthenticationManager getAuthenticationManager() throws Exception {
           
           
       //...
       for (GlobalAuthenticationConfigurerAdapter config : this.globalAuthConfigurers) {
           
           
          authBuilder.apply(config);
       }//1
       this.authenticationManager = authBuilder.build();//2
       //...
       return this.authenticationManager;
    }
    
    1. The builder uses the global authentication configuration, which is mentioned earlier when creating AuthenticationConfiguration

    2. Build the authentication manager

      Look directly at the last doBuild()

      AbstractConfiguredSecurityBuilder

      protected final O doBuild() throws Exception {
                
                
         synchronized (this.configurers) {
                
                
            this.buildState = BuildState.INITIALIZING;
            beforeInit();//1
            init();//2
            this.buildState = BuildState.CONFIGURING;
            beforeConfigure();//3
            configure();//4
            this.buildState = BuildState.BUILDING;
            O result = performBuild();//5
            this.buildState = BuildState.BUILT;
            return result;
         }
      }
      
      1. Operation before initialization

      2. Initialize the configurator

      3. Operation before configuration

      4. Configure the configurator. There are many configurators, so I won’t talk about it. The configuration process is as follows:

        AbstractConfiguredSecurityBuilder

        private void configure() throws Exception {
                     
                     
           Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
           for (SecurityConfigurer<O, B> configurer : configurers) {
                     
                     
              configurer.configure((B) this);
           }
        }
        
      5. start building

        This method creates and returns a PrivideManager

        AuthenticationManagerBuilder.java

        protected ProviderManager performBuild() throws Exception {
                     
                     
           ProviderManager providerManager = new ProviderManager(this.authenticationProviders,
                 this.parentAuthenticationManager);
           return providerManager;
        }
        
  5. Create , inject the HttpSecuritypreviousPrividerHttpSecurity

  6. HttpSecurityConfigure the basic configurator


configurationSecurityFilterChain

After the default HttpSecurityconfiguration is complete, it will start to configure the default SecurityFilterChain,

Let's look at the SecurityAutoConfigurationimported SpringBootWebSecurityConfigurationclasses

SpringBootWebSecurityConfiguration.java

@Configuration(proxyBeanMethods = false)
@ConditionalOnDefaultWebSecurity//1
@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().httpBasic();
      return http.build();//2
   }

}
  1. This class will only be configured when the default WebSecurity is met, as follows:

    @Conditional(DefaultWebSecurityCondition.class)//1
    public @interface ConditionalOnDefaultWebSecurity {
           
           }
    class DefaultWebSecurityCondition extends AllNestedConditions {
           
           
    	DefaultWebSecurityCondition() {
           
           super(ConfigurationPhase.REGISTER_BEAN);}
    	@ConditionalOnClass({
           
            SecurityFilterChain.class, HttpSecurity.class })
    	static class Classes {
           
           }//2
    	@ConditionalOnMissingBean({
           
            WebSecurityConfigurerAdapter.class, SecurityFilterChain.class })
    	static class Beans {
           
           }//3
    }
    
    
    1. meet DefaultWebSecurityConditionthe conditions
    2. Satisfied with SecurityFilterChain.class, HttpSecurity.classtwo classes
    3. Meet the lack WebSecurityConfigurerAdapter.classof SecurityFilterChain.classtwo beans, and the default Security configuration is missing these two classes
  2. Create the default basic SecurityFilterChain, where the SecurityFilterChain has fifteen basic Filters:

    Fifteen basic Filters


configurationWebSecurity

After configuring the default basic SecurityFilterChain, it will be configuredWebSecurity

we see WebSecurityConfigurationclass

First look at how it is configured WebSecurity, as follows:

WebrSecurityConfiguration.java

@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
      @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)//1
      throws Exception {
    
    
   this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
   webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);//2
   Integer previousOrder = null;
   Object previousConfig = null;
   for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
    
    
      Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
      previousOrder = order;
      previousConfig = config;
   }//3
   for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
    
    
      this.webSecurity.apply(webSecurityConfigurer);
   }//4
   this.webSecurityConfigurers = webSecurityConfigurers;
}
  1. First look at the formal parameters with annotations @Value. This annotation gets all the previously configured WebSeucurityConfigurer(that is, customized WebSecurityConfigurer), and it will pass all the configurators to the currently created ones below WebSecurity.
  2. createWebSecurity
  3. Sort fetched (custom)SecurityConfigurer
  4. Pass the obtained (custom) SecurityConfigurerconfigurator into the current WebSecuirty, apply uses the configurator, needless to say

Configure the finalFilterChainProxy

After configuration WebSecurity, basic SecurityFilterChain, will configure the finalSecurityFilterChain

WebSecurityConfiguration.java

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
    
    
   if (!hasConfigurers && !hasFilterChain) {
    
    
      WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor
            .postProcess(new WebSecurityConfigurerAdapter() {
    
    
            });
      this.webSecurity.apply(adapter);
   }//1
   for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
    
    
      this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
      for (Filter filter : securityFilterChain.getFilters()) {
    
    
         if (filter instanceof FilterSecurityInterceptor) {
    
    
            this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
            break;
         }
      }
   }//2
   for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
    
    
      customizer.customize(this.webSecurity);
   }//3
   return this.webSecurity.build();//4
}
  1. FilterChainCreate if not present FilterChain, either custom or default, usually withFilterChain

  2. WebSecurityset upFilterSecurityInterceptor

  3. Configure custom WebSecurity, the custom class needs to implement WebSecurityCustomizerthe interface

    WebSecurityConfiguration.java

    @Autowired(required = false)
    void setWebSecurityCustomizers(List<WebSecurityCustomizer> webSecurityCustomizers) {
            
            
       this.webSecurityCustomizers = webSecurityCustomizers;
    }
    
  4. Return to the final reconfigured WebSecuriity( SecurityFilterChainfinal version)

    buid()I won’t talk much about the method. I AuthenticationConfigurationalso mentioned it when configuring [HttpSecurity] (# Configure HttpSecurity) before. Here we mainly analyze the different AbstractConfiguredSecurityBuilderinheritance performBuild()methods

    WebSecurity.java

    @Override
    protected Filter performBuild() throws Exception {
           
           
       int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
       List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
       List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> requestMatcherPrivilegeEvaluatorsEntries = new ArrayList<>();
       for (RequestMatcher ignoredRequest : this.ignoredRequests) {
           
           
          SecurityFilterChain securityFilterChain = new DefaultSecurityFilterChain(ignoredRequest);
          securityFilterChains.add(securityFilterChain);
          requestMatcherPrivilegeEvaluatorsEntries
                .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
       }
       for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
           
           
          SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
          securityFilterChains.add(securityFilterChain);
          requestMatcherPrivilegeEvaluatorsEntries
                .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
       }
       if (this.privilegeEvaluator == null) {
           
           
          this.privilegeEvaluator = new RequestMatcherDelegatingWebInvocationPrivilegeEvaluator(
                requestMatcherPrivilegeEvaluatorsEntries);
       }
       FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
       if (this.httpFirewall != null) {
           
           
          filterChainProxy.setFirewall(this.httpFirewall);
       }
       if (this.requestRejectedHandler != null) {
           
           
          filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler);
       }
       filterChainProxy.afterPropertiesSet();
    
       Filter result = filterChainProxy;
        
       this.postBuildAction.run();
       return result;
    }
    

    Analysis shows that the function of this method is to add the default SecurityFilterChain filter and WebSecurity filter to the newly created FilterChainProxy and return


end

At this point, Spring Security roughly defaults to the start-up process source code analysis is over

Guess you like

Origin blog.csdn.net/HHoao/article/details/124573922