第一个就是这个 add 方法,这相当于是在收集所有的配置类 。将所有的 xxxConfigure 收集起来存储到 configurers 中,将来再统一初始化并配置,configurers 本身是一个 LinkedHashMap,key 是配置类的 class,value 是一个集合,集合里边放着 xxxConfigure 配置类 。当需要对这些配置类进行集中配置的时候,会通过 getConfigurers 方法获取配置类,这个获取过程就是把 LinkedHashMap 中的 value 拿出来,放到一个集合中返回 。
另一个方法就是 doBuild 方法 。
@Overrideprotected 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); }}
在 AbstractSecurityBuilder 类中,过滤器的构建被转移到 doBuild 方法上面了,不过在 AbstractSecurityBuilder 中只是定义了抽象的 doBuild 方法,具体的实现在 AbstractConfiguredSecurityBuilder 。
doBuild 方法就是一边更新状态,进行进行初始化 。
beforeInit 是一个预留方法,没有任何实现 。
init 方法就是找到所有的 xxxConfigure,挨个调用其 init 方法进行初始化 。
beforeConfigure 是一个预留方法,没有任何实现 。
configure 方法就是找到所有的 xxxConfigure,挨个调用其 configure 方法进行配置 。
最后则是 performBuild 方法,是真正的过滤器链构建方法,但是在 AbstractConfiguredSecurityBuilder 中 performBuild 方法只是一个抽象方法,具体的实现在 HttpSecurity 中 。
这便是 HttpSecurity 所有父类、父接口的功能 。
看完了父辈,接下来回到我们今天文章的主题,HttpSecurity 。
2. HttpSecurityHttpSecurity 做的事情,就是进行各种各样的 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 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 方法,将当前配置 configurer 收集起来 。
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;}
推荐阅读
- 虞美人陈与义阅读理解
- 邦威古茶树你理解没,过渡性茶树
- 什么是MQ?什么是RabbitMQ?能做什么?简单理解一下?
- 网站安全维护SQL攻击防护方案
- 如何理解周礼一书中体现的内部控制制度 中国古代组织管理思想也许起源于周礼
- 资深架构师:深入聊聊获取屏幕高度这件事
- 轻松理解机器学习算法:Adaboost算法
- 并发编程之定时任务&定时线程池原理解析
- 图解Raft:应该是最容易理解的分布式一致性算法
- 无锁队列Disruptor原理解析