SpringSecurity源码-构建ProviderManager
简介
在构建WenSecurity执行生命周期AbstractConfiguredSecurityBuilder#doBuild()方法中的init(),会执行到WebSecurityConfigurerAdapter#init(WebSecurity web) 方法,会去创建HttpSecurity。在创建HttpSecurity时调用authenticationManager()构建ProviderManager。
 
WebSecurityConfigurerAdapter#authenticationManager()
	protected AuthenticationManager authenticationManager() throws Exception {
	if (!this.authenticationManagerInitialized) {
		configure(this.localConfigureAuthenticationBldr);
		if (this.disableLocalConfigureAuthenticationBldr) {
			this.authenticationManager = this.authenticationConfiguration.getAuthenticationManager();
		}
		else {
			this.authenticationManager = this.localConfigureAuthenticationBldr.build();
		}
		this.authenticationManagerInitialized = true;
	}
	return this.authenticationManager;
}
默认调用authenticationConfiguration.getAuthenticationManager()构建AuthenticationManager,即ProviderManager。authenticationConfiguration是通过@Autowired自动注入的。
AuthenticationConfiguration来源
@EnableWebSecurity注解导入了@EnableGlobalAuthentication,看看@EnableGlobalAuthentication定义:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {
}
@EnableGlobalAuthentication导入了配置类AuthenticationConfiguration。这个AuthenticationConfiguration就是WebSecurityConfigurerAdapter中的AuthenticationConfiguration字段要注入的配置类。
看看AuthenticationConfiguration类中重要的方法:
@Bean
public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor,
		ApplicationContext context) {
	LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
	AuthenticationEventPublisher authenticationEventPublisher = getAuthenticationEventPublisher(context);
	DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(
			objectPostProcessor, defaultPasswordEncoder);
	if (authenticationEventPublisher != null) {
		result.authenticationEventPublisher(authenticationEventPublisher);
	}
	return result;
}
    @Bean
public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(
		ApplicationContext context) {
	return new EnableGlobalAuthenticationAutowiredConfigurer(context);
}
@Bean
public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(
		ApplicationContext context) {
	return new InitializeUserDetailsBeanManagerConfigurer(context);
}
@Bean
public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(
		ApplicationContext context) {
	return new InitializeAuthenticationProviderBeanManagerConfigurer(context);
}
创建了一个DefaultPasswordEncoderAuthenticationManagerBuilder bean和三个类型GlobalAuthenticationConfigurerAdapter的bean。
现在看看authenticationConfiguration.getAuthenticationManager():
	public AuthenticationManager getAuthenticationManager() throws Exception {
	if (this.authenticationManagerInitialized) {
		return this.authenticationManager;
	}
	AuthenticationManagerBuilder authBuilder = this.applicationContext.getBean(AuthenticationManagerBuilder.class);
	if (this.buildingAuthenticationManager.getAndSet(true)) {
		return new AuthenticationManagerDelegator(authBuilder);
	}
	for (GlobalAuthenticationConfigurerAdapter config : this.globalAuthConfigurers) {
		authBuilder.apply(config);
	}
	this.authenticationManager = authBuilder.build();
	if (this.authenticationManager == null) {
		this.authenticationManager = getAuthenticationManagerBean();
	}
	this.authenticationManagerInitialized = true;
	return this.authenticationManager;
}
authBuilder就是上面的DefaultPasswordEncoderAuthenticationManagerBuilder。globalAuthConfigurers集合就是上面的EnableGlobalAuthenticationAutowiredConfigurer,InitializeUserDetailsBeanManagerConfigurer,InitializeAuthenticationProviderBeanManagerConfigurer。调用authBuilder.apply方法将EnableGlobalAuthenticationAutowiredConfigurer,InitializeUserDetailsBeanManagerConfigurer,InitializeAuthenticationProviderBeanManagerConfigurer加入到DefaultPasswordEncoderAuthenticationManagerBuilder的configurers属性中。
调用authBuilder.build()创建AuthenticationManager。
DefaultPasswordEncoderAuthenticationManagerBuilder类继承结构如下:

DefaultPasswordEncoderAuthenticationManagerBuilder继承了AbstractConfiguredSecurityBuilder。DefaultPasswordEncoderAuthenticationManagerBuilder#build()会调用到AbstractConfiguredSecurityBuilder#doBuild()执行生命周期构建。重点看init(),configure(),performBuild()。init()方法会调用configurers集合的中每个元素的init()方法。DefaultPasswordEncoderAuthenticationManagerBuilder中的configurers集合有EnableGlobalAuthenticationAutowiredConfigurer,InitializeUserDetailsBeanManagerConfigurer,InitializeAuthenticationProviderBeanManagerConfigurer。
 
DefaultPasswordEncoderAuthenticationManagerBuilder执行configurer类的init方法
EnableGlobalAuthenticationAutowiredConfigurer#init(AuthenticationManagerBuilder auth)
	@Override
	public void init(AuthenticationManagerBuilder auth) {
		Map<String, Object> beansWithAnnotation = this.context
				.getBeansWithAnnotation(EnableGlobalAuthentication.class);
		if (logger.isTraceEnabled()) {
			logger.trace(LogMessage.format("Eagerly initializing %s", beansWithAnnotation));
		}
	}
打印了日志。
 
先分别执行EnableGlobalAuthenticationAutowiredConfigurer,InitializeUserDetailsBeanManagerConfigurer,InitializeAuthenticationProviderBeanManagerConfigurer的init方法。
InitializeAuthenticationProviderBeanManagerConfigurer#init(AuthenticationManagerBuilder auth)
    @Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
	auth.apply(new InitializeAuthenticationProviderManagerConfigurer());
}
将InitializeAuthenticationProviderManagerConfigurer配置加入到DefaultPasswordEncoderAuthenticationManagerBuilder中的configurersAddedInInitializing属性和configurers属性。
InitializeUserDetailsBeanManagerConfigurer#init(AuthenticationManagerBuilder auth)
public void init(AuthenticationManagerBuilder auth) throws Exception {
	auth.apply(new InitializeUserDetailsManagerConfigurer());
}
将InitializeUserDetailsManagerConfigurer配置加入到DefaultPasswordEncoderAuthenticationManagerBuilder中的configurersAddedInInitializing属性和configurers属性。
 
执行完后DefaultPasswordEncoderAuthenticationManagerBuilder中的configurers集合有五个元素。执行完EnableGlobalAuthenticationAutowiredConfigurer,InitializeUserDetailsBeanManagerConfigurer,InitializeAuthenticationProviderBeanManagerConfigurer的init方法后又执行InitializeAuthenticationProviderManagerConfigurer,InitializeUserDetailsManagerConfigurer的init方法,这两个类的init方法是空方法,就不谈了。
 
DefaultPasswordEncoderAuthenticationManagerBuilder执行configurer类的configure方法
现在分别执行上面五个configurer的configure方法。三个类EnableGlobalAuthenticationAutowiredConfigurer,InitializeUserDetailsBeanManagerConfigurer,InitializeAuthenticationProviderBeanManagerConfigurer的configure是空方法就不谈了。
InitializeAuthenticationProviderManagerConfigurer#configure(AuthenticationManagerBuilder auth)
	@Override
	public void configure(AuthenticationManagerBuilder auth) {
		if (auth.isConfigured()) {
			return;
		}
		AuthenticationProvider authenticationProvider = getBeanOrNull(AuthenticationProvider.class);
		if (authenticationProvider == null) {
			return;
		}
		auth.authenticationProvider(authenticationProvider);
	}
默认AuthenticationProvider是null。
 
InitializeUserDetailsManagerConfigurer#configure(AuthenticationManagerBuilder auth)
public void configure(AuthenticationManagerBuilder auth) throws Exception {
		if (auth.isConfigured()) {
			return;
		}
		UserDetailsService userDetailsService = getBeanOrNull(UserDetailsService.class);
		if (userDetailsService == null) {
			return;
		}
		PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
		UserDetailsPasswordService passwordManager = getBeanOrNull(UserDetailsPasswordService.class);
		DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
		provider.setUserDetailsService(userDetailsService);
		if (passwordEncoder != null) {
			provider.setPasswordEncoder(passwordEncoder);
		}
		if (passwordManager != null) {
			provider.setUserDetailsPasswordService(passwordManager);
		}
		provider.afterPropertiesSet();
		auth.authenticationProvider(provider);
	}
创建了DaoAuthenticationProvider并添加到DefaultPasswordEncoderAuthenticationManagerBuilder的authenticationProviders字段中。
DefaultPasswordEncoderAuthenticationManagerBuilder执行performBuild方法
AuthenticationManagerBuilder#performBuild()
protected ProviderManager performBuild() throws Exception {
	if (!isConfigured()) {
		this.logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
		return null;
	}
	ProviderManager providerManager = new ProviderManager(this.authenticationProviders,
			this.parentAuthenticationManager);
	if (this.eraseCredentials != null) {
		providerManager.setEraseCredentialsAfterAuthentication(this.eraseCredentials);
	}
	if (this.eventPublisher != null) {
		providerManager.setAuthenticationEventPublisher(this.eventPublisher);
	}
	providerManager = postProcess(providerManager);
	return providerManager;
}
将authenticationProviders集合添加到ProviderManager中。authenticationProviders默认是DaoAuthenticationProvider。调用postProcess让ProviderManager执行Spring的Bean创建流程。
                    
                
                
            
        
浙公网安备 33010602011771号