- AuthenticationConfiguration是认证管理器的配置类,当没有重写下面方法的时候会通过此配置类构建全局认证管理器
public abstract class WebSecurityConfigurerAdapter implements
......
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
this.disableLocalConfigureAuthenticationBldr = true;
}
......
}
1、重要方法
1.1 authenticationManagerBuilder()
@Configuration(proxyBeanMethods = false)
@Import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
......
@Bean
public AuthenticationManagerBuilder authenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor,
ApplicationContext context) {
LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context,
AuthenticationEventPublisher.class);
DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(
objectPostProcessor, defaultPasswordEncoder);
if (authenticationEventPublisher != null) {
result.authenticationEventPublisher(authenticationEventPublisher);
}
return result;
}
......
}
1.1.2 LazyPasswordEncoder
- LazyPasswordEncoder是SpringSecurity创建的全局认证管理器的时候,创建的懒加载机制的密码编码器
- 可以看出不管是匹配密码还是更新密码都是从容器获取PasswordEncoder达到一个懒加载的作用
static class LazyPasswordEncoder implements PasswordEncoder {
private ApplicationContext applicationContext;
private PasswordEncoder passwordEncoder;
LazyPasswordEncoder(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public String encode(CharSequence rawPassword) {
return getPasswordEncoder().encode(rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return getPasswordEncoder().matches(rawPassword, encodedPassword);
}
@Override
public boolean upgradeEncoding(String encodedPassword) {
return getPasswordEncoder().upgradeEncoding(encodedPassword);
}
private PasswordEncoder getPasswordEncoder() {
if (this.passwordEncoder != null) {
return this.passwordEncoder;
}
PasswordEncoder passwordEncoder = getBeanOrNull(this.applicationContext, PasswordEncoder.class);
if (passwordEncoder == null) {
passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
this.passwordEncoder = passwordEncoder;
return passwordEncoder;
}
}
1.2 三大配置类
- 这里的配置类指的是全局认证管理器构建器的配置类
- 但实际上这些配置类本身没什么作用,重点是又导入了两个配置类
- InitializeUserDetailsManagerConfigurer
- InitializeAuthenticationProviderManagerConfigurer
public class AuthenticationConfiguration {
......
@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);
}
......
}
1.2.1 InitializeUserDetailsManagerConfigurer
- 分析configure方法可以得出一个结论,根据注册一个UserDetailsService,PasswordEncoder,UserDetailsPasswordService给全局认证管理器构建器注册一个AuthenticationProvider(认证提供者)
class InitializeUserDetailsManagerConfigurer extends GlobalAuthenticationConfigurerAdapter {
@Override
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);
}
private <T> T getBeanOrNull(Class<T> type) {
String[] beanNames = InitializeUserDetailsBeanManagerConfigurer.this.context.getBeanNamesForType(type);
if (beanNames.length != 1) {
return null;
}
return InitializeUserDetailsBeanManagerConfigurer.this.context.getBean(beanNames[0], type);
}
}
1.2.2 InitializeUserDetailsManagerConfigurer
- 分析configure方法可以得出,是直接从容器中获取AuthenticationProvider然后注册到全局认证管理器构建器中
class InitializeUserDetailsManagerConfigurer
extends GlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) {
if (auth.isConfigured()) {
return;
}
AuthenticationProvider authenticationProvider = getBeanOrNull(
AuthenticationProvider.class);
if (authenticationProvider == null) {
return;
}
auth.authenticationProvider(authenticationProvider);
}
private <T> T getBeanOrNull(Class<T> type) {
String[] userDetailsBeanNames = InitializeAuthenticationProviderBeanManagerConfigurer.this.context
.getBeanNamesForType(type);
if (userDetailsBeanNames.length != 1) {
return null;
}
return InitializeAuthenticationProviderBeanManagerConfigurer.this.context
.getBean(userDetailsBeanNames[0], type);
}
}
2、AuthenticationManagerBuilder工作流程
- 根据SpringSecurcity的构建流程分为以下几步,前面几步都是在根据上面说的配置类进行初始化
@Override
protected final O doBuild() throws Exception {
synchronized (this.configurers) {
this.buildState = BuildState.INITIALIZING;
beforeInit();
init();
this.buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
this.buildState = BuildState.BUILDING;
O result = performBuild();
this.buildState = BuildState.BUILT;
return result;
}
}
- 唯有performBuild()方法没有看
- 作用就是生成ProviderManager(认证管理器)
public class AuthenticationManagerBuilder
extends
AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder>
implements ProviderManagerBuilder<AuthenticationManagerBuilder> {
@Override
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;
}
}
