SecurityConfigurer 在 Spring Security 中是一个非常重要的角色。Spring Security 过滤器链中的每一个过滤器,都是通过 xxxConfigurer 来进行配置的,而这些 xxxConfigurer 实际上都是 SecurityConfigurer 的实现。
public interface SecurityConfigurer> { //一个初始化方法 void init(B builder) throws Exception; //一个配置方法。这里只是规范了方法的定义,具体的实现则在不同的实现类中 void configure(B builder) throws Exception; }
SecurityConfigurer 有三种类型实现类:SecurityConfigurerAdapter,GlobalAuthenticationConfigurerAdapter和WebSecurityConfigurer
而本文所讲的全局配置器GlobalAuthenticationConfigurerAdapter
一、GlobalAuthenticationConfigurerAdapterGlobalAuthenticationConfigurerAdapter 看名字就知道是一个跟全局配置有关的东西,它本身实现了 SecurityConfigurerAdapter 接口,但是并未对方法做具体的实现,只是将泛型具体化了:
@Order(100) public abstract class GlobalAuthenticationConfigurerAdapter implements SecurityConfigurer{ public void init(AuthenticationManagerBuilder auth) throws Exception { } public void configure(AuthenticationManagerBuilder auth) throws Exception { } }
可以看到,SecurityConfigurer 中的泛型,现在明确成了 AuthenticationManager 和 AuthenticationManagerBuilder。所以 GlobalAuthenticationConfigurerAdapter 的实现类将来主要是和配置 AuthenticationManager 有关。当然也包括默认的用户名密码也是由它的实现类来进行配置的。
我们在 Spring Security 中使用的 AuthenticationManager 其实可以分为两种,一种是局部的,另一种是全局的,这里主要是全局的配置。
二、InitializeUserDetailsBeanManagerConfigurer@Order(InitializeUserDetailsBeanManagerConfigurer.DEFAULT_ORDER)
class InitializeUserDetailsBeanManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
static final int DEFAULT_ORDER = Ordered.LOWEST_PRECEDENCE - 5000;
private final ApplicationContext context;
InitializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {
this.context = context;
}
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
//创建其内部类InitializeUserDetailsManagerConfigurer
auth.apply(new InitializeUserDetailsManagerConfigurer());
}
class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
if (auth.isConfigured()) {
return;
}
//从容器中获取UserDetailsService,如果没有直接返回
UserDetailsService userDetailsService = getBeanOrNull( UserDetailsService.class);
if (userDetailsService == null) {return;}
//从容器中获取PasswordEncoder
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
//从容器中获取UserDetailsPasswordService
UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
//创建DaoAuthenticationProvider,将3个类配置进去
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
if (passwordEncoder != null) {
provider.setPasswordEncoder(passwordEncoder);
}
if (passwordManager != null) {
provider.setUserDetailsPasswordService(passwordManager);
}
provider.afterPropertiesSet();
auth.authenticationProvider(provider);
}
}
}
他的注册发生在配置类AuthenticationConfiguration中
@Configuration(proxyBeanMethods = false)
@import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
@Bean
public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {
return new InitializeUserDetailsBeanManagerConfigurer(context);
}
}
二、InitializeAuthenticationProviderBeanManagerConfigurer
@Order(InitializeAuthenticationProviderBeanManagerConfigurer.DEFAULT_ORDER)
class InitializeAuthenticationProviderBeanManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
InitializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) {
this.context = context;
}
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
//创建内部类InitializeUserDetailsManagerConfigurer
auth.apply(new InitializeUserDetailsManagerConfigurer());
}
class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) {
if (auth.isConfigured()) {
return;
}
//从容器中获取AuthenticationProvider,如果没有直接返回
AuthenticationProvider authenticationProvider = getBeanOrNull( AuthenticationProvider.class);
if (authenticationProvider == null) {
return;
}
auth.authenticationProvider(authenticationProvider);
}
//忽略方法。。。。
}
}
他的注册也发生在配置类AuthenticationConfiguration中
@Configuration(proxyBeanMethods = false)
@import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
@Bean
public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) {
return new InitializeAuthenticationProviderBeanManagerConfigurer(context);
}
}
EnableGlobalAuthenticationAutowiredConfigurer只是为了记录标注@EnableGlobalAuthentication的类
注意GlobalAuthenticationConfigurerAdapter子类的注册都在配置类AuthenticationConfiguration中,而AuthenticationConfiguration是通过
@EnableGlobalAuthentication引入的,所以@EnableGlobalAuthentication注解是开启全局配置器的关键,当然了,在springboot环境,我们不需要手动配置@EnableGlobalAuthentication,因为springboot帮我们引入了
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
//继承了@EnableGlobalAuthentication
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {
}



