概述
spring-boot-starter-security和spring其它系列的starter一样,依赖spring-boot-autoconfigure,根据其META-INF下的spring.factories加载自动配置类,然后进行一系列的初始化配置。查看spring.factories下的EnableAutoConfiguration和spring-security相关的一共有以下几种自动配置
1 2 3 4 5 6
   | SecurityAutoConfiguration SecurityRequestMatcherProviderAutoConfiguration UserDetailsServiceAutoConfiguration SecurityFilterAutoConfiguration ReactiveSecurityAutoConfiguration ReactiveUserDetailsServiceAutoConfiguration
   | 
 
下面对这些自动配置类进行简单的分析
SecurityAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | @Configuration
  @ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
  @EnableConfigurationProperties(SecurityProperties.class)
  @Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,       SecurityDataConfiguration.class }) public class SecurityAutoConfiguration {        @Bean        @ConditionalOnMissingBean(AuthenticationEventPublisher.class)    public DefaultAuthenticationEventPublisher authenticationEventPublisher(          ApplicationEventPublisher publisher) {       return new DefaultAuthenticationEventPublisher(publisher);    }
  }
   | 
 
SecurityRequestMatcherProviderAutoConfiguration
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
   | @Configuration
  @ConditionalOnClass({ RequestMatcher.class })
  @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public class SecurityRequestMatcherProviderAutoConfiguration {
     @Configuration        @ConditionalOnClass(DispatcherServlet.class)        @ConditionalOnBean(HandlerMappingIntrospector.class)    public static class MvcRequestMatcherConfiguration {
        @Bean              @ConditionalOnClass(DispatcherServlet.class)       public RequestMatcherProvider requestMatcherProvider(             HandlerMappingIntrospector introspector) {          return new MvcRequestMatcherProvider(introspector);       }
     }
     @Configuration        @ConditionalOnClass(ResourceConfig.class)        @ConditionalOnMissingClass("org.springframework.web.servlet.DispatcherServlet")        @ConditionalOnBean(JerseyApplicationPath.class)    public static class JerseyRequestMatcherConfiguration {
        @Bean       public RequestMatcherProvider requestMatcherProvider(             JerseyApplicationPath applicationPath) {          return new JerseyRequestMatcherProvider(applicationPath);       }
     }
  }
   | 
 
UserDetailsServiceAutoConfiguration
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
   | @Configuration
  @ConditionalOnClass(AuthenticationManager.class)
  @ConditionalOnBean(ObjectPostProcessor.class)
  @ConditionalOnMissingBean({ AuthenticationManager.class, AuthenticationProvider.class,       UserDetailsService.class }) public class UserDetailsServiceAutoConfiguration {
     private static final String NOOP_PASSWORD_PREFIX = "{noop}";
     private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern          .compile("^\\{.+}.*$");
     private static final Log logger = LogFactory          .getLog(UserDetailsServiceAutoConfiguration.class);
     @Bean    @ConditionalOnMissingBean(          type = "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository")    @Lazy    public InMemoryUserDetailsManager inMemoryUserDetailsManager(          SecurityProperties properties,          ObjectProvider<PasswordEncoder> passwordEncoder) {       SecurityProperties.User user = properties.getUser();       List<String> roles = user.getRoles();       return new InMemoryUserDetailsManager(User.withUsername(user.getName())             .password(getOrDeducePassword(user, passwordEncoder.getIfAvailable()))             .roles(StringUtils.toStringArray(roles)).build());    }
     private String getOrDeducePassword(SecurityProperties.User user,          PasswordEncoder encoder) {       String password = user.getPassword();       if (user.isPasswordGenerated()) {          logger.info(String.format("%n%nUsing generated security password: %s%n",                user.getPassword()));       }       if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) {          return password;       }       return NOOP_PASSWORD_PREFIX + password;    }
  }
   | 
 
SecurityFilterAutoConfiguration
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
   | @Configuration
  @ConditionalOnWebApplication(type = Type.SERVLET)
  @EnableConfigurationProperties(SecurityProperties.class)
  @ConditionalOnClass({ AbstractSecurityWebApplicationInitializer.class,       SessionCreationPolicy.class })
  @AutoConfigureAfter(SecurityAutoConfiguration.class) public class SecurityFilterAutoConfiguration {
     private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;
     @Bean        @ConditionalOnBean(name = DEFAULT_FILTER_NAME)    public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(          SecurityProperties securityProperties) {       DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(             DEFAULT_FILTER_NAME);       registration.setOrder(securityProperties.getFilter().getOrder());       registration.setDispatcherTypes(getDispatcherTypes(securityProperties));       return registration;    }
     private EnumSet<DispatcherType> getDispatcherTypes(          SecurityProperties securityProperties) {       if (securityProperties.getFilter().getDispatcherTypes() == null) {          return null;       }       return securityProperties.getFilter().getDispatcherTypes().stream()             .map((type) -> DispatcherType.valueOf(type.name())).collect(Collectors                   .collectingAndThen(Collectors.toSet(), EnumSet::copyOf));    }
  }
   | 
 
剩下的ReactiveSecurityAutoConfiguration和ReactiveUserDetailsServiceAutoConfiguration是spring5新增的reactive非阻塞的web框架中的配置类,不在本次的讨论之中,就不做分析了。
总结
本章主要分析了spring-security在项目启动时主要加载了哪些自动配置类,从spring-boot-autoconfigure的META-INF下的spring.factories文件中,我们可以发现,在项目启动时主要是加载SecurityAutoConfiguration
SecurityRequestMatcherProviderAutoConfiguration、UserDetailsServiceAutoConfiguration、
SecurityFilterAutoConfiguration这四个配置类,接下来的文章我们将围绕这四个配置类分析spring-security究竟为我们做了哪些自动配置。