「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」
- 一开始我们解析了
WebSecurity的结构图,这时候我们在加入两个同级别的角色AuthenticationManagerBuilder、HttpSecurity。 这两个角色上面都已经出现过了。所以这里更新了下结构图。 - 相信你读到这里一定晕了,我也很无奈,不过读源码就是这样唯一的方式就是坚持!现在我们想想我们是因为啥走到这一步的。入口是
webSecurity.build。 最终是AbstractConfiguredSecurityBuilder.doBuild开始执行四状态三步骤中的第一步init , init内部执行了WebSecurityConfigurerAdapter#init。该方法中我们又从getHttp方法进入。在getHttp中需要获取认证管理器。认证管理器需要借助AuthenticationManagerBuilder类型的localConfigureAuthenticationBldr来进行build 。 而通过图示我们知道AuthenticationManagerBuilder和WebSecurity拥有相同的图结构。 - 所以此时为了获取
AuthenticationManagerBuilder我们不得不重新执行下AbstractConfiguredSecurityBuilder#doBuild流程。 - 不说了。我是阵亡了。今天到此结束!明天再来继续往下看!!!!!!
AuthenticationManagerBuilder新开始build
-
今天我们需要抛开昨天
WebSecurity#build的生命周期,因为在websecurity的init阶段就开始了AuthenticationManagerBuilder的build的生命周期了。所以有必要先解决AuthenticationManagerBuilder的生命周期。在build之前我们先看下昨天获取认证管理器的地方 -
第一步是configure(AuthenticationMangersBuilder) 。 这个是我们配置类中扩展的方法。
auth.inMemoryAuthentication()
- 点进去内部方法是一个apply方法
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
throws Exception {
return apply(new InMemoryUserDetailsManagerConfigurer<>());
}
-
这个apply方法和
WebSecurity中一样,将配置赋值给configures 。 -
这个类和我们
SecurityConfig是一样的结构。都是继承SecurityConfigurerAdapter。但是WebSecurity中的configures是WebSecurityConfigurerAdapter . 看源码我们能够知道InMemoryUserDetrailsManagerConfigurer没有实现init方法,所以在AuthenticationMangersBuilder#build中init是空。有了这部分我们在继续开始build操作。
private void init() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.init((B) this);
}
for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
configurer.init((B) this);
}
}
- 因为
AuthenticationMangersBuilder的configurers没有实现init , 所以不会产生任何逻辑那么configurersAddedInInitializing也就是空了。所以整体的init没啥逻辑可言。
AuthenticationMangersBuilder中的CONFIGURING状态
- 随着时间的推移下面我们来到的AuthenticationMangersBuilder#build过程中的CONFIGURING状态了。
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
- configure方法也很简单,就是执行configures中的configure方法。在这里configures是我们配置的
InMemoryUserDetailsManagerConfigurer。还是上面那个结构图他的直系类是UserDetailsManagerConfigurer。最终的configure执行落在UserDetailsServiceConfigurer类上。
@Override
public void configure(B builder) throws Exception {
initUserDetailsService();
super.configure(builder);
}
- initUserDetailsService有落在了
UserDetailsManagerConfigurer上。
public final UserDetailsBuilder withUser(String username) {
UserDetailsBuilder userBuilder = new UserDetailsBuilder((C) this);
userBuilder.username(username);
this.userBuilders.add(userBuilder);
return userBuilder;
}
- 而上面initUserDetailsService里需要通过userBuilders来创建用户。这个userBuilders正是我们配置类中withUser创建的信息。
- 然后交由父类
AbstractDaoAuthenticationConfigurer#configure来完成。父类里就是对provider进行初始化,初始化的过程也是借助objectPostProcessor来完成。这里就不多做介绍了。 - 一句话总结
AuthenticationMangersBuilder#configure的作用就是加载用户信息,我们的案例就是从内存中加载用户信息。