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创建流程。

posted @ 2023-04-10 20:38  shigp1  阅读(231)  评论(0)    收藏  举报