Spring Security (三) WebSecurity

Scroll Down

Spring Security WebSecurity

1.概要

上一章已经讲解到了SpringSecurity用到了建造者模式来建造FilterChainProxy。本片就来详细分析下WebSecurity的核心逻辑以及AbstractConfiguredSecurityBuilder的doBuild()方法。

2.AbstractConfiguredSecurityBuilder中安全配置类

SpringSecurity通过SecurityConfigurer来建造FilterChainProxy,建造前还需要进行配置。因此AbstractConfiguredSecurityBuilder还需要注入配置组件SecurityConfigurer,初始化配置组件SecurityConfigurer,调用SecurityConfigurer的configure方法。

在AbstractConfiguredSecurityBuilder类中,看下安全配置类的定义:‘

image-20210726202843930

这是定义的安全配置器的子类Map集合,这个configurers就是用于初始化以及配置FilterChainProxy中的filters用的。Map集合中,Key是SecurityConfigurer的子类的Class类型,Value是SecurityConfigurer的list集合。

作为一个成员变量,自然会有方法从外部注入安全配置类。在AbstractConfiguredSecurityBuilder的类中,定义了add方法。

image-20210726203931890

下图可以发现 add()方法的使用场景

image-20210726204339072

查看 apply()方法调用,可发现HttpSecurity的getOrApply方法有调用该方法。

image-20210726204933119

getOrApply方法主要是从configurers集合中获取配置类,如果存在则直接返回,否则则应用该配置类。

通过查看可得调用getOrApply的方法的有很多,

ExpressionUrlAuthorizationConfigurer配置类为例,看下其类内部configure方法逻辑。

通过不断继承 我们不断往父类查找,发现configure的实现是在ExpressionUrlAuthorizationConfigurer的抽象父类AbstractInterceptUrlConfigurer定义的。

image-20210726205944782

  • 通过createMetadataSource方法为FilterSecurityInterceptor提供 FilterInvocationSecurityMetadataSource

image-20210726205612260

  • 通过createFilterSecurityInterceptor方法创建 FilterSecurityInterceptor

image-20210726210505038

ExpressionUrlAuthorizationConfigurer的抽象父类AbstractInterceptUrlConfigurer可以看出,configure方法中调用了一个postProcess方法,该方法用于生成FilterSecurityInterceptor对象,在本系列文章前面第一章以及列出来的FilterChainProxy拦截器链对象,可以知道FilterSecurityInterceptor对象就属于FilterChainProxy拦截器链中的对象,并且是处在最后一个位置。

到此处,安全配置类的作用已经提现出来了,就是向sharedObject中添加过滤器,并最终注入到FilterChainProxy中。

3.AbstractConfiguredSecurityBuilder的doBuild()方法

configurers集合元素的注入完成之后,就是进行建造工作,调用doBuild()方法。

image-20210726211302095

beforeInit()和beforeConfigure()是一个空方法体,没有逻辑,可被子类覆盖。其作为钩子存在,方便不使用SecurityConfigurer情况下切入到生命周期

image-20210726211608413

其次便是init方法,这需要注意的是,init和configure方法是有接口SecurityConfigurer接口定义的,但其实现以由SecurityConfigurerAdapter这个抽象的适配器类实现了,所以最终的安全配置类可重写init()和configure(),也可以不重写。所以可以发现,很多安全配置类是没有重写init()方法的。接下来调用 configure方法。

image-20210726212531461

在前面已经已经以ExpressionUrlAuthorizationConfigurer为例,去查看安全配置类configure方法的作用,都知道安全配置类的configure方法是用于将过滤器添加到sharedObject缓存中。

经过init()和configure()方法的执行,已经可以开始进行建造工作了,因而调用performBuild()方法执行建造过程。

image-20210726212842987

可以看到在AbstractConfiguredSecurityBuilder中,performBuild是以抽象方法的形式存在的,所以实现逻辑都在其子类中。

image-20210726213106315

这里HttpSecurity和WebSecurity类名这么像,有什么异同呢?

HttpSecurity

HttpSecurity允许为特定的http请求配置基于Web的安全特性。默认情况下,HttpSecurity将应用于所有请求,但是如果需要限制请求,则可以通过RequestMatcher或其他类似方法来进行限制。

WebSecurity

而WebSecurity是通过WebSecurityConfiguration创建的,用于去创建类FilterChainProxy。在SpringSecurity中,WebSecurity通过HttpSecurity来对某些请求进行拦截限制。

区别

WebSecurity用于建造FilterChainProxy,WebSecurity是包含HttpSecurity的一个更大的概念,而HttpSecurity仅是用于建造FilterChainProxy中的一个SecurityFilterChain。

4. WebSecurity中的performBuild()方法

WebSecurity重写了AbstractConfiguredSecurityBuilder的perfomBuild()方法,核心逻辑如下

image-20210726215629875

performBuild()方法中,会执行securityFilterChainBuilderbuild()方法,该方法又会去迭代执行doBuild()方法,最终返回一个SecurityFilterChain对象。

综上,本文对WebSecurity的建造逻辑进行了概括性的讲解,更加深入的内容还需要进行代码debug跟踪深入查看,这样才能加深对于WebSecurity的理解。

5.总结

  • 安全配置类是在HttpSecurityxxConfigurerAdapter等类中进行添加
  • WebSecurityHttpSecurity区别在于,WebSecurity是用于建造FilterChainProxy的,它是包含HttpSecurity;而HttpSecurity是用于对请求进行限制,同时还用于建造DefaultSecurityFilterChain
  • 安全配置类主要是通过configure方法向sharedObject缓存对象中添加过滤器,并最终添加进FilterChainProxy过滤器链中
  • WebSecurity建造FilterChainProxy的核心逻辑可以笼统的分为三步:安全配置了初始化、安全配置类configure的调用、performBuild的调用

感谢CoderBruis 主流框架分析 :https://github.com/coderbruis/JavaSourceCodeLearning