- 1、配置与构建分离- 1.1、构建
- 1.2、配置- 1.2.1、SecuriryConfigurer
- 1.2.2、GlobalAuthenticationConfigurerAdapter
- 1.2.3、WebSecurityConfigurer
- 1.2.4、SecurityConfigurerAdapter- 1.2.4.1、UserDetailsAwareConfigurer
- 1.2.4.2、AbstractDaoAuthenticationConfigurer
- 1.2.4.3、UserDetailsServiceConfigurer
- 1.2.4.4、UserDetailsManagerConfigurer
- 1.2.4.5、JdbcUserDetailsManagerConfigurer
- 1.2.4.6、InMemoryUserDetailsManagerConfigurer
- 1.2.4.7、AbstractHttpConfigurer
- 1.2.4.8、AbstractAuthenticationFilterConfigurer📌
- 1.2.4.9、FormLoginConfigurer📌
 
 
 
1、配置与构建分离
作为一个框架,尤其是安全框架,配置必须足够灵活才能使用于更多的业务场景。Spring Security采取了配置与构建分离的架构设计来保证这一点。配置只需去收集配置项,构建只需要把所有的配置构建成目标对象。各干各的,分离职责,这种做法能够提高代码的可维护性和可读写性。Spring Security利用接口隔离把配置和构建进行高度抽象,提高灵活度,降低复杂度。不过这个体系依然十分庞大。为了降低学习难度,需要把大问题拆解成小问题,各个击破,这种学习方法在学习一些复杂的抽象理论时很奏效。
1.1、构建
1.1.1、SecurityBuilder
SecurityBuilder就是对构建的抽象。
public interface SecurityBuilder<O> {
O build() throws Exception;
}
1.1.2、HttpSecurityBuilder
HttpSecurityBuilder是一个接口,继承自SecurityBuilder接口,其中泛型为DefaultSecurityFilterChain,那么HttpSecurityBuilder接口的作用就是对DefaultSecurityFilterChain的构建进行了增强,为其构建增加了一些额外的获取配置和管理配置的入口。
public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>> extends
SecurityBuilder<DefaultSecurityFilterChain> {
<C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C getConfigurer(
Class<C> clazz);
<C extends SecurityConfigurer<DefaultSecurityFilterChain, H>> C removeConfigurer(
Class<C> clazz);
<C> void setSharedObject(Class<C> sharedType, C object);
<C> C getSharedObject(Class<C> sharedType);
H authenticationProvider(AuthenticationProvider authenticationProvider);
H userDetailsService(UserDetailsService userDetailsService) throws Exception;
H addFilterAfter(Filter filter, Class<? extends Filter> afterFilter);
H addFilterBefore(Filter filter, Class<? extends Filter> beforeFilter);
H addFilter(Filter filter);
}
- getConfigurer方法用于获取一个配置对象。Spring Security过滤器中的所有过滤器对象都是由- xxxConfigurer来进行配置的,这里就是用于获取- xxxConfigurer对象。
- removeConfigurer方法用于移除一个配置对象。
- setSharedObject和- getSharedObject方法用于配置或获取由多个- SecurityConfigurer共享的对象。
- authenticationProvider方法用于配置认证验证器。
- userDetailsService方法用于配置数据源接口。
- addFilterAfter方法用于在某一个过滤器之后添加过滤器。
- addFilterBefore方法用于在某一个过滤器之前添加过滤器。
- addFilter方法用于添加一个过滤器,该过滤器必须是现有过滤器链中的某一个过滤器或其扩展。
HttpSecurityBuilder接口定义的这些方法在HttpSecurity中都将得到实现。
1.1.3、AbstractSecurityBuilder
AbstractSecurityBuilder是对SecurityBuilder的实现。源码如下:
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
private AtomicBoolean building = new AtomicBoolean();
private O object;
public final O build() throws Exception {
if (this.building.compareAndSet(false, true)) {
// 构建的核心逻辑由钩子方法提供
this.object = doBuild();
return this.object;
}
throw new AlreadyBuiltException("This object has already been built");
}
// 构建目标对象
public final O getObject() {
if (!this.building.get()) {
throw new IllegalStateException("This object has not been built");
}
return this.object;
}
// 钩子方法
protected abstract O doBuild() throws Exception;
}
可以看到,这里重写了build方法,并加了final关键字,不可覆写!在build方法中,通过原子类AtomicBoolean对构建方法build方法进行了调用限制:每个目标对象只能被构建一次,避免安全策略发生不一致的情况。构建的核心逻辑通过预留的钩子方法doBuild来扩展,钩子方法是很常见的一种继承策略,将来在子类中实现具体逻辑。AbstractSecurityBuilder还提供了获取已构建目标对象的方法getObject。
1.1.4、AbstractConfiguredSecurityBuilder
AbstractConfiguredSecurityBuilder是AbstractSecurityBuilder的子类。AbstractConfiguredSecurityBuilder定义了一个枚举类,将整个构建过程分为5种状态,也可以理解为构建过程生命周期的五个阶段,如下:
private enum BuildState {
UNBUILT(0),
INITIALIZING(1),
CONFIGURING(2),
BUILDING(3),
BUILT(4);
private final int order;
BuildState(int order) {
this.order = order;
}
public boolean isInitializing() {
return INITIALIZING.order == order;
}
public boolean isConfigured() {
return order >= CONFIGURING.order;
}
}
五种状态分别是UNBUILT``INITIALIZING``CONFIGURING``BUILDING以及BUILT。另外还提供了两个判断方法,isInitializing判断是否正在初始化阶段,isConfigured表示是否已经构建完成。AbstractConfiguredSecurityBuilder中的方法比较多,在这里只列出两个关键的方法:
- 第一个方法就是这个 - add方法,这相当于在收集所有的配置。将所有的- xxxConfigurer收集起来存储到- configurers中,将来再统一初始化并配置。- configurers本身是一个- LinkedHashMap,key 是配置类的 class,value 是- xxxConfigurer配置类集合。当需要对这些配置类进行集中配置的时候,会通过- getConfigurers方法获取配置类集合,这个获取过程就是就是把- LinkedHashMap中的 value 拿出来,放到一个集合中返回。- private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
- Assert.notNull(configurer, "configurer cannot be null");
- Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
- .getClass();
- synchronized (configurers) {
- if (buildState.isConfigured()) {
- throw new IllegalStateException("Cannot apply " + configurer
- + " to already built object");
- }
- List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
- .get(clazz) : null;
- if (configs == null) {
- configs = new ArrayList<>(1);
- }
- configs.add(configurer);
- this.configurers.put(clazz, configs);
- if (buildState.isInitializing()) {
- this.configurersAddedInInitializing.add(configurer);
- }
- }
- }
- private Collection<SecurityConfigurer<O, B>> getConfigurers() {
- List<SecurityConfigurer<O, B>> result = new ArrayList<>();
- for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) {
- result.addAll(configs);
- }
- return result;
- }
 
- 另一个方法就是 - doBuild方法。在- AbstractSecurityBuilder类中,构建的核心逻辑被放到- doBuild方法上,但是- AbstractSecurityBuilder类中只是定义了抽象的- doBuild方法,真正的实现还是在该类中的- doBuild方法。- @Override
- 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;
- }
- }
- 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);
- }
- }
- private void configure() throws Exception {
- Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
- for (SecurityConfigurer<O, B> configurer : configurers) {
- configurer.configure((B) this);
- }
- }
 - doBuild方法就是一边更新状态一边进行构建。- beforeInit是一个预留方法,没有任何实现;- init方法就是找到所有的- xxxConfigurer,挨个调用其- init方法进行初始化;- beforeConfigure是一个预留方法,没有任何实现;- configure方法就是找到所有的- xxxConfigurer,挨个调用其- configure方法进行配置;- performBuild方法是真正的过滤器链构建方法,但是在当前- AbstractConfiguredSecurityBuilder中的- performBuild方法只是一个抽象方法,具体的实现在- HttpSecurity类中。- 1.1.5、HttpSecurity📌- public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
- implements SecurityBuilder<DefaultSecurityFilterChain>, HttpSecurityBuilder<HttpSecurity> {
- }
 - 其中, - HttpSecurity的继承关系图: 
 可以看到,- HttpSecurity继承自- AbstractConfiguredSecurityBuilder,同时实现了- SecurityBuilder和- HttpSecurityBuilder两个接口。
 结合上面- HttpSecurity的源码,- HttpSecurity实现- SecurityBuilder接口时传入的泛型为- DefaultSecurityFilterChain,那么可以很清楚的知道- HttpSecurity就是用来构建- DefaultSecurityFilterChain对象的了。- 1.1.5.1、DefaultSecurityFilterChain- 那么 - DefaultSecurityFilterChain是什么呢🤔?相信大家看过前面的Spring Security过滤器架构(源码篇)
 文章,知道- SecurityFilterChain是我们平时所说的过滤器链。- public interface SecurityFilterChain {
- boolean matches(HttpServletRequest request);
- List<Filter> getFilters();
- }
 - SecurityFilterChain接口中只定义了两个方法,一个是- matches方法用来匹配请求;另外一个是- getFilters方法返回一个- List集合,集合中放着- Filter对象。当一个请求到来时,用- matches方法去比较请求是否和当前过滤器链吻合,如果吻合,那么当前请求会逐个经过- getFilters方法返回的- List集合中的过滤器。- SecurityFilterChain接口只有一个实现类,那就是- DefaultSecurityFilterChain:- public final class DefaultSecurityFilterChain implements SecurityFilterChain {
- private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);
- private final RequestMatcher requestMatcher;
- private final List<Filter> filters;
- public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
- this(requestMatcher, Arrays.asList(filters));
- }
- public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
- logger.info("Creating filter chain: " + requestMatcher + ", " + filters);
- this.requestMatcher = requestMatcher;
- this.filters = new ArrayList<>(filters);
- }
- public RequestMatcher getRequestMatcher() {
- return requestMatcher;
- }
- public List<Filter> getFilters() {
- return filters;
- }
- public boolean matches(HttpServletRequest request) {
- return requestMatcher.matches(request);
- }
- @Override
- public String toString() {
- return "[ " + requestMatcher + ", " + filters + "]";
- }
- }
 - DefaultSecurityFilterChain只是对- SecurityFilterChain中的方法进行了实现,并没有特别值得说的地方。从上面的介绍中,大家可以看到,- DefaultSecurityFilterChain其实就相当于Spring Security 中的过滤器链,一个- DefaultSecurityFilterChain代表一个过滤器链,如果系统中存在多个过滤器链,则会存在多个- DefaultSecurityFilterChain对象。- 1.1.5.2、HttpSecurity- HttpSecurity做的事情就是进行各种各样的- xxxConfigurer配置。如:- public CorsConfigurer<HttpSecurity> cors() throws Exception {
- return getOrApply(new CorsConfigurer<>());
- }
- public CsrfConfigurer<HttpSecurity> csrf() throws Exception {
- ApplicationContext context = getContext();
- return getOrApply(new CsrfConfigurer<>(context));
- }
- public FormLoginConfigurer<HttpSecurity> formLogin() throws Exception {
- return getOrApply(new FormLoginConfigurer<>());
- }
- public ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling() throws Exception {
- return getOrApply(new ExceptionHandlingConfigurer<>());
- }
 - HttpSecurity中有大量类似的方法,可以在此处对过滤器中的过滤器一个一个进行配置。
 每个配置方法的结尾都会使用- getOrApply方法,这个方法是干嘛的呢?🤔- private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(
- C configurer) throws Exception {
- C existingConfig = (C) getConfigurer(configurer.getClass());
- if (existingConfig != null) {
- return existingConfig;
- }
- return apply(configurer);
- }
 - getConfigurer方法是在它的父类- AbstractConfiguredSecurityBuilder中定义的,目的是就是去查看当前这个- xxxConfigurer是否已经配置过了。如果当前- xxxConfigurer已经配置过了,则直接返回,否则调用- apply方法,这个- apply方法最终会调用父类- AbstractConfiguredSecurityBuilder中的- add方法,将当前- xxxConfigurer配置收集起来。- HttpSecurity中还有一个- addFilter方法:- public HttpSecurity addFilter(Filter filter) {
- Class<? extends Filter> filterClass = filter.getClass();
- if (!comparator.isRegistered(filterClass)) {
- throw new IllegalArgumentException(
- "The Filter class "
- + filterClass.getName()
- + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
- }
- this.filters.add(filter);
- return this;
- }
 - 这个 - addFilter方法的作用主要是在各个- xxxConfigurer进行配置的时候,会调用这个方法,(- xxxConfigurer就是用来配置过滤器的),把- Filter过滤器都添加到- filters变量中。如在1.2.4.8章节中的- AbstractAuthenticationFilterConfigurer的- configure方法中就被用到,将配置好的- UsernamePasswordAuthenticationFilter过滤器添加到- filters变量中。
 最终在- HttpSecurity重写父类- performBuild方法,构建出来一个过滤器链:- @Override
- protected DefaultSecurityFilterChain performBuild() {
- filters.sort(comparator);
- return new DefaultSecurityFilterChain(requestMatcher, filters);
- }
 - 先给过滤器排序,然后构造出 - DefaultSecurityFilterChain过滤器链。- 1.2、配置- 1.2.1、SecuriryConfigurer- SecuriryConfigurer本身是一个接口:- public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
- void init(B builder) throws Exception;
- void configure(B builder) throws Exception;
- }
 - 可以看到, - SecuriryConfigurer中主要定义了两个方法:- init初始化方法和- configure配置方法。这里只是规范了方法的定义,具体的实现则在不同的实现类中。
 需要注意的是这两个方法的参数类型都是一个泛型B,也就是- SecurityBuilder的子类,关于- SecurityBuilder,在上面的章节已经介绍过了。- SecuriryConfigurer有三个实现类:
- GlobalAuthenticationConfigurerAdapter
- WebScurityConfigurer
- 
1.2.2、GlobalAuthenticationConfigurerAdapterGlobalAuthenticationConfigurerAdapter实现了SecuriryConfigurer接口,但是并未对方法做具体的实现,只是将泛型具体化了。- @Order(100)
- public abstract class GlobalAuthenticationConfigurerAdapter implements
- SecurityConfigurer<AuthenticationManager, AuthenticationManagerBuilder> {
- public void init(AuthenticationManagerBuilder auth) throws Exception {
- }
- public void configure(AuthenticationManagerBuilder auth) throws Exception {
- }
- }
 可以看到, SecurityConfigurer中的泛型,现在明确成了AuthenticationManager和AuthenticationManagerBuilder。所以GlobalAuthenticationConfigurerAdapter的实现类主要是和配置AuthenticationManager有关。当然也包括默认的用户名和密码也是由它的实现类进行配置的。1.2.3、WebSecurityConfigurer这个接口其实就是我们天天用的 WebSecurityConfigurerAdapter类所实现的接口,所以WebSecurityConfigurer的作用就非常明确了,用于用户扩展自定义配置。1.2.4、SecurityConfigurerAdapterSecurityConfigurerAdapter实现了SecuriryConfigurer接口,我们使用的大部分xxxConfigurer全都是SecurityConfigurerAdapter的子类。SecurityConfigurerAdapter在SecuriryConfigurer的基础上,还扩展出了几个非常好用的方法:- public abstract class SecurityConfigurerAdapter<O, B extends SecurityBuilder<O>>
- implements SecurityConfigurer<O, B> {
- private B securityBuilder;
- private CompositeObjectPostProcessor objectPostProcessor = new CompositeObjectPostProcessor();
- public void init(B builder) throws Exception {
- }
- public void configure(B builder) throws Exception {
- }
- public B and() {
- return getBuilder();
- }
- protected final B getBuilder() {
- if (securityBuilder == null) {
- throw new IllegalStateException("securityBuilder cannot be null");
- }
- return securityBuilder;
- }
- @SuppressWarnings("unchecked")
- protected <T> T postProcess(T object) {
- return (T) this.objectPostProcessor.postProcess(object);
- }
- public void addObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
- this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor);
- }
- public void setBuilder(B builder) {
- this.securityBuilder = builder;
- }
- private static final class CompositeObjectPostProcessor implements
- ObjectPostProcessor<Object> {
- private List<ObjectPostProcessor<?>> postProcessors = new ArrayList<>();
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public Object postProcess(Object object) {
- for (ObjectPostProcessor opp : postProcessors) {
- Class<?> oppClass = opp.getClass();
- Class<?> oppType = GenericTypeResolver.resolveTypeArgument(oppClass,
- ObjectPostProcessor.class);
- if (oppType == null || oppType.isAssignableFrom(object.getClass())) {
- object = opp.postProcess(object);
- }
- }
- return object;
- }
- private boolean addObjectPostProcessor(
- ObjectPostProcessor<?> objectPostProcessor) {
- boolean result = this.postProcessors.add(objectPostProcessor);
- postProcessors.sort(AnnotationAwareOrderComparator.INSTANCE);
- return result;
- }
- }
- }
 
- 首先一开始声明了一个CompositeObjectPostProcessor实例,CompositeObjectPostProcessor是ObjectPostProcessor的一个实现,ObjectPostProcessor本身是一个后置处理器,该后置处理器默认有两个实现,AutowireBeanFactoryObjectPostProcessor和CompositeObjectPostProcessor。其中,AutowireBeanFactoryObjectPostProcessor主要是利用了AutowireCapableBeanFactory对Bean进行手动注册,因为在Spring Secuirty 中,很多对象都是手动 new 出来的,这个 new 出来的对象和容器没有任何关系,利用AutowireCapableBeanFactory可以将这些手动 new 出来的对象注入到容器中,AutowireBeanFactoryObjectPostProcessor的主要作用就是完成这件事;CompositeObjectPostProcessor则是一个复合的对象处理器,里面维护了一个list集合,这个list集合中,大部分情况下只存储一条数据,那就是AutowireBeanFactoryObjectPostProcessor用来完成对象注入到容器的操作,如果用户手动调用了addObjectPostProcessor方法,那么CompositeObjectPostProcessor集合中维护的数据就会多出来一条,在CompositeObjectPostProcessor#postProcess方法中,会遍历集合中的所有ObjectPostProcessor,挨个调用postProcess方法对对象进行后置处理。😵晕,这里看不懂有什么用,我们继续让下看!!!
- and方法,该方法返回值是一个- SecurityBuilder,- SecurityBuilder实际上就是- HttpSecurity,我们在- HttpSecurity中去配置不同过滤器时,可以使用- and方法进行链式配置,就是因为这里定义了- and方法并返回了- SecurityBuilder实例。
SecurityConfigurerAdapter也有几个主要的子类:
- UserDetailsAwareConfigurer
- 
1.2.4.1、UserDetailsAwareConfigurer1.2.4.2、AbstractDaoAuthenticationConfigurerAbstractDaoAuthenticationConfigurer中所做的事情比较简单,主要是构造了一个默认的DaoAuthenticationProvider,并为其配置PasswordEncoder和UserDetailsService。1.2.4.3、UserDetailsServiceConfigurerUserDetailsServiceConfigurer重写了AbstractDaoAuthenticationConfigurer中的configure方法,在configure方法执行之前加入了initUserDetailsService方法,以方便按照自己的方式去初始化UserDetailsService。不过这里的initUserDetailsService方法是一个空方法。1.2.4.4、UserDetailsManagerConfigurerUserDetailsManagerConfigurer中实现了UserDetailsServiceConfigurer中定义的initUserDetailsService方法,具体的实现逻辑就是将UserDetailsBuilder所构建出来的UserDetails以及提前准备好的UserDetails中的用户存储到UserDetailsService中。
 该类同时添加了withUser方法用来添加用户,同时还增加了一个UserDetailsBuilder用来构建用户。1.2.4.5、JdbcUserDetailsManagerConfigurerJdbcUserDetailsManagerConfigurer在父类的基础上补充了DataSource对象,同时还提供了相应的数据库查询方法。1.2.4.6、InMemoryUserDetailsManagerConfigurerInMemoryUserDetailsManagerConfigurer在父类的基础上重写了构造方法,将父类中的UserDetailsService实例定义为InMemoryUserDetailsManager。
 📌上面的内容简单来说就是:上面的配置类在执行configure方法的时候,使用 new 出来的UserDetailsManager创建用户。如InMemoryUserDetailsManagerConfigurer就使用InMemoryUserDetailsManager创建用户存到内存当中。1.2.4.7、AbstractHttpConfigurerAbstractHttpConfigurer这一派中的东西非常多,我们所有的过滤器配置,都是它的子类。 AbstractHttpConfigurer继承自SecurityConfigurerAdapter,并增加了两个方法,disable方法和withObjectPostProcessor方法:- public abstract class AbstractHttpConfigurer<T extends AbstractHttpConfigurer<T, B>, B extends HttpSecurityBuilder<B>>
- extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, B> {
- /**
- * Disables the {@link AbstractHttpConfigurer} by removing it. After doing so a fresh
- * version of the configuration can be applied.
- *
- * @return the {@link HttpSecurityBuilder} for additional customizations
- */
- @SuppressWarnings("unchecked")
- public B disable() {
- getBuilder().removeConfigurer(getClass());
- return getBuilder();
- }
- @SuppressWarnings("unchecked")
- public T withObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
- addObjectPostProcessor(objectPostProcessor);
- return (T) this;
- }
- }
 
- 我们常用的.csrf().disable()就是出自这里,其实disable的实现原理就是从getBuilder中移除相关的xxxConfigurer。getBuilder方法实际上获取到的是HttpSecurity,所以移除掉xxxConfigurer实际上就是从过滤器链中移除某一个过滤器,例如.csrf().disable()就是移除掉处理csrf的过滤器。
- 另一个增加的方法是 - withObjectPostProcessor,这是为配置类手动添加后置处理器的。在- AbstractHttpConfigurer的父类中其实有一个类似的方法就是- addObjectPostProcessor,但是- addObjectPostProcessor只是一个添加方法,返回值为- void,而- withObjectPostProcessor的返回值是当前配置类,也就是- xxxConfigurer,所以使用- withObjectPostProcessor方法的话,就可以使用链式配置。- 1.2.4.8、AbstractAuthenticationFilterConfigurer📌- AbstractAuthenticationFilterConfigurer类中的功能比较多,源码也是相当长,不过我们只需要抓住两点,- init方法和- configure方法,因为这两个方法是所有- xxxConfigurer的灵魂。- @Override
- public void init(B http) throws Exception {
- updateAuthenticationDefaults();
- updateAccessDefaults(http);
- registerDefaultAuthenticationEntryPoint(http);
- }
 - init方法只要干了三件事:
- updateAuthenticationDefaults方法主要是配置默认的登录处理地址,失败跳转地址,注销成功跳转地址。
- updateAccessDefaults方法主要是对登录页,登录处理地址和失败跳转地址默认进行- permitAll配置(如果用户配置permitAll=true的话)。
- registerDefaultAuthenticationEntryPoint方法则是注册异常处理器。
再来看下configure方法:
@Override
public void configure(B http) throws Exception {
PortMapper portMapper = http.getSharedObject(PortMapper.class);
if (portMapper != null) {
authenticationEntryPoint.setPortMapper(portMapper);
}
RequestCache requestCache = http.getSharedObject(RequestCache.class);
if (requestCache != null) {
this.defaultSuccessHandler.setRequestCache(requestCache);
}
authFilter.setAuthenticationManager(http
.getSharedObject(AuthenticationManager.class));
authFilter.setAuthenticationSuccessHandler(successHandler);
authFilter.setAuthenticationFailureHandler(failureHandler);
if (authenticationDetailsSource != null) {
authFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
}
SessionAuthenticationStrategy sessionAuthenticationStrategy = http
.getSharedObject(SessionAuthenticationStrategy.class);
if (sessionAuthenticationStrategy != null) {
authFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
}
RememberMeServices rememberMeServices = http
.getSharedObject(RememberMeServices.class);
if (rememberMeServices != null) {
authFilter.setRememberMeServices(rememberMeServices);
}
F filter = postProcess(authFilter);
http.addFilter(filter);
}
configure方法中的逻辑很简单,构建各种各样的回调函数给authFilter,其实就是UsernamePasswordAuthenticationFilter,authFilter再去postProcess中走一圈注册到Spring容器中,最后再把authFilter添加到过滤器链中。
1.2.4.9、FormLoginConfigurer📌
public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {
FormLoginCongurer继承自AbstractAuthenticationFilterConfigurer类,明确了AbstractAuthenticationFilterConfigurer中的泛型是UsernamePasswordAuthenticationFilter,也就是说FormLoginCongurer最终要配置的是UsernamePasswordAuthenticationFilter过滤器。FormLoginCongurer重写了init方法,配置了一下默认的登录页面,其他的基本上都来自父类,未做太多改变。
另外我们日常配置的很多东西都来自这里:
好啦,这就是FormLoginCongurer这个配置类,用于配置UsernamePasswordAuthenticationFilter过滤器。其他的xxxConfigurer十分类似,每个xxxConfigurer都对应了一个不同的Filter。
 
 
                         
                                

