- • AuthenticationConfiguration是认证管理器的配置类,当没有重写下面方法的时候会通过此配置类构建全局认证管理器
public abstract class WebSecurityConfigurerAdapter implements
......
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
this.disableLocalConfigureAuthenticationBldr = true;
}
......
}
1、重要方法
1.1 authenticationManagerBuilder()
- • 作用是往容器中注册一个全局认证管理器构建器
@Configuration(proxyBeanMethods = false)
// 导入了AutowireBeanFactoryObjectPostProcessor
@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 {
/**
* 尝试获得有关认证的相关对象
* @param auth 一般情况都是全局认证管理器
* @throws Exception
*/
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
if (auth.isConfigured()) {
return;
}
//尝试获取UserDetailsService
UserDetailsService userDetailsService = getBeanOrNull(UserDetailsService.class);
//如果UserDetailsService都没有,都不能加载用户,也就用不着PasswordEncoder,那就直接返回
if (userDetailsService == null) {
return;
}
//尝试获取PasswordEncoder
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
//尝试获取UserDetailsPasswordService
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);
}
/**
* 如果只找到一个bean,则返回被请求类的bean,否则返回null
* @param type
*/
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);
}
/**
* @return
*/
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;
}
}
- • 流程图
image.png