在以前的文章中咱们提到了WebSecurityConfigurerAdapter中的两个web
configure(WebSecurity web)
configure(HttpSecurity http)app
然而还有一个很是重要的configure方法,咱们在继承WebSecurityConfigurerAdapter时能够经过覆盖下面这个configure来配置认证信息ide
configure(AuthenticationManagerBuilder auth)函数
其实这个configure的套路与configure(HttpSecurity http)相似,也是经过对它的参数进行配置,至于怎么配置就是调用AuthenticationManagerBuilder里的方法,他的方法也大都会注册一个configurer,而后又是会调用到以下的方法:post
protected final O doBuild() throws Exception {
synchronized (configurers) {
buildState = BuildState.INITIALIZING;
beforeInit();
init();
buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
buildState = BuildState.BUILDING;
O result = performBuild();
buildState = BuildState.BUILT;
return result;
}
}ui
这个和以前的configure(HttpSecurity http)套路同样。只是这个是配置AuthenticationManagerBuilder,那个是配置HttpSecurity,或者说AuthenticationManagerBuilder维护了一组认证信息,HttpSecurity维护了一组filter。this
咱们先看performBuild()方法:spa
在AuthenticationManagerBuilder类中debug
protected ProviderManager performBuild() throws Exception {
if (!isConfigured()) {
logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
return null;
}
ProviderManager providerManager = new ProviderManager(authenticationProviders,
parentAuthenticationManager);
if (eraseCredentials != null) {
providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
}
if (eventPublisher != null) {
providerManager.setAuthenticationEventPublisher(eventPublisher);
}
providerManager = postProcess(providerManager);
return providerManager;
}
orm
他最终返回了一个providerManager,有什么用先不说,咱们能够看到关键的参数authenticationProviders,从名字来看,providerManager是用来维护authenticationProviders的。那authenticationProviders是怎么来的呢,想一想就知道应该是咱们调用了AuthenticationManagerBuilder里的某些配置方法注册了某些configurer,而后在上面那个doBuild里的configure();中依次调用这些configurer里的configure方法建立了authenticationProvider,而后把它加入到authenticationProviders中。
举个例子:咱们有时会继承WebSecurityConfigurerAdapter而后覆盖他的configure(AuthenticationManagerBuilder auth)方法,以下:
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("root")
.password("root")
.roles("USER");
}
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
throws Exception {
return apply(new InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>());
}
咱们能够看到InMemoryUserDetailsManagerConfigurer是个configurer,apply就是把configurer注册到AuthenticationManagerBuilder维护的configurers,nMemoryAuthentication()返回InMemoryUserDetailsManagerConfigurer对象,继续调用withUser等方法就是为了建立一个UserDetailsBuilder对象()里面包括用户名,密码,角色之类的信息),而后放入UserDetailsManagerConfigurer中的userBuilders中
而后等上面那个doBuild()里调用configure();时,InMemoryUserDetailsManagerConfigurer这个configurer中的configure方法会被调用,也就是 UserDetailsServiceConfigurer中的
public void configure(B builder) throws Exception {
initUserDetailsService();
super.configure(builder);
}
protected void initUserDetailsService() throws Exception {
for (UserDetailsBuilder userBuilder : userBuilders) {
getUserDetailsService().createUser(userBuilder.build());
}
}
这里能够看到把以前的userBuilders里的全部userBuilder放入userDetailsService的实现类中来维护,对应InMemoryUserDetailsManagerConfigurer他的userDetailsService的实现类是InMemoryUserDetailsManager。接着看那个super.configure(builder);
public void configure(B builder) throws Exception {
provider = postProcess(provider);
builder.authenticationProvider(provider);
}
这个builder就是AuthenticationManagerBuilder类型,provider是以下类型:
private DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
由AbstractDaoAuthenticationConfigurer中的初始化函数可知provider用来维护userDetailsService,也就是说每套用户认证信息都会被放到userDetailsService中维护,而后这个provider维护这个userDetailsService。
protected AbstractDaoAuthenticationConfigurer(U userDetailsService) {
this.userDetailsService = userDetailsService;
provider.setUserDetailsService(userDetailsService);
}
而后继续前面那个configure
public void configure(B builder) throws Exception {
provider = postProcess(provider);
builder.authenticationProvider(provider);
}
public AuthenticationManagerBuilder authenticationProvider(
AuthenticationProvider authenticationProvider) {
this.authenticationProviders.add(authenticationProvider);
return this;
}
能够看到这里真正把Provider放到了authenticationProviders(开篇提到的那个authenticationProviders),因此能够看出,AuthenticationManagerBuilder里configurers中的每一个configurer都能生成一个Provider,就像HttpSecurity中的每一个configurer都能生成一个filter相似,而后统一由一个对象管理。