当前 Spring Security 版本:5.1.5-RELEASE [Spring Cloud Security 官方文档] [Spring Security 官方文档]

一、架构原理

image.png
如图, Spring Security 运行主要由三个类组成:

  • DelegatingFilterProxy(Filter)
  • FilterChainProxy(Filter)
  • SecurityFilterChain(非 Filter 不过持有 FilterChain)

上述三大组件构成了 Spring Security 运行逻辑。

1.1、DelegatingFilterProxy(Filter)

作为入口,在剔除 Spring Security Servlet 支持时可以从该类入手。

中文译名:委托过滤代理。
DelegatingFilterProxy 是一个过滤器。
DelegatingFilterProxy 作为整个 Spring Security 的处理入口。
DelegatingFilterProxy 将整个 spring security 功能集成到 Filter 中。
DelegatingFilterProxy 是一个入口,或者说是一个桥接器,本身不做任何认证授权等相关处理。

DelegatingFilterProxy(Filter) 作为中转将 Spring Security 功能集成到了 Servlet 容器中。并将关于 Spring Security 的操作委派给FilterChainProxy 处理

拓展: DelegatingFilterProxy 持有 FilterChainProxy 方式。 借助 Spring ICO 容器,调用 getBean(String beanName) 的方式从容器中获取对象。 a、配置类 AbstractSecurityWebApplicationInitializer 定义了bean 名称为: springSecurityFilterChain 。并设置到 DelegatingFilterProxy 中。 image.png b、 DelegatingFilterProxy 在第一次调用 doFilter() 方法时,从 IOC 容器中获取实例对象。 image.png

1.2、FilterChainProxy(Filter)

FilterChainProxy 被封装到 DelegatingFilterProxy 中。

Spring Security servlet 支持相关功能包含在 FilterChainProxy 中。

FilterChainProxy 通过 SecurityFilterChain 将请求交给许多 Filter 实例构建的过滤器链处理。

相关处理逻辑代码如下:
image.png

拓展: FilterChainProxy 在 spring boot 中配置方式。 FilterChainProxy配置位置: WebSecurityConfiguration (配置类通过 @EnableWebSecurity 注解触发).。 配置代码如下: image.png

1.3、SecurityFilterChain(非 Filter)

SecurityFilterChain 对象实例存在于 FilterChainProxy 中,且 FilterChainProxy持有的是 List<SecurityFilterChain>

FilterChainProxy 能够根据 RequestMatcher 匹配 URL 对应的 SecurityFilterChain
针对不同 URL 提供了不同的 FilterChainProxy 处理能力。

特殊情况下,同一个 URL 匹配多个 SecurityFilterChain ,但是也只有第一次匹配到的 SecurityFilterChain 会被执行。原因如下:
image.png

二、Security Filter(Security 功能实现)

Spring Security 运行主要由三个类组成:

  • DelegatingFilterProxy(Filter)
  • FilterChainProxy(Filter)
  • SecurityFilterChain(非 Filter 不过持有 FilterChain)

具体 Spring Security 功能的实现,由 SecurityFilterChain 中持有的 Filter 过滤器链实现。

Spring Security 默认提供的 Filter
官方文档

  • ChannelProcessingFilter
  • WebAsyncManagerIntegrationFilter
  • SecurityContextPersistenceFilter
  • HeaderWriterFilter
  • CorsFilter
  • CsrfFilter
  • LogoutFilter
  • OAuth2AuthorizationRequestRedirectFilter
  • Saml2WebSsoAuthenticationRequestFilter
  • X509AuthenticationFilter
  • AbstractPreAuthenticatedProcessingFilter
  • CasAuthenticationFilter
  • OAuth2LoginAuthenticationFilter
  • Saml2WebSsoAuthenticationFilter
  • [UsernamePasswordAuthenticationFilter](https://docs.spring.io/spring-security/site/docs/5.5.x/reference/html5/#servlet-authentication-usernamepasswordauthenticationfilter)
  • OpenIDAuthenticationFilter
  • DefaultLoginPageGeneratingFilter
  • DefaultLogoutPageGeneratingFilter
  • ConcurrentSessionFilter
  • [DigestAuthenticationFilter](https://docs.spring.io/spring-security/site/docs/5.5.x/reference/html5/#servlet-authentication-digest)
  • BearerTokenAuthenticationFilter
  • [BasicAuthenticationFilter](https://docs.spring.io/spring-security/site/docs/5.5.x/reference/html5/#servlet-authentication-basic)
  • RequestCacheAwareFilter
  • SecurityContextHolderAwareRequestFilter
  • JaasApiIntegrationFilter
  • RememberMeAuthenticationFilter
  • AnonymousAuthenticationFilter
  • OAuth2AuthorizationCodeGrantFilter
  • SessionManagementFilter
  • [ExceptionTranslationFilter](https://docs.spring.io/spring-security/site/docs/5.5.x/reference/html5/#servlet-exceptiontranslationfilter)
  • [FilterSecurityInterceptor](https://docs.spring.io/spring-security/site/docs/5.5.x/reference/html5/#servlet-authorization-filtersecurityinterceptor)
  • SwitchUserFilter

Spring Security 中,重点在于 认证授权

下面以基于用户名、密码进行认证授权为例。

2.1、认证:UsernamePasswordAuthenticationFilter

实现接口:Filter 等。

image.png

2.1.1、抽象父类:AbstractAuthenticationProcessingFilter

AbstractAuthenticationProcessingFilter 定义了 Spring Security 身份认证的基础流程,流程图如下:

[spring-security]-[servlet]-架构原理 - 图8
流程步骤

step1、构建凭证对象

AbstractAuthenticationProcessingFilterHttpServletRequest 中获取用户提交的凭证信息,构建认证对象,具体对象依赖于 AbstractAuthenticationProcessingFilter 子类的实现。 如: UsernamePasswordAuthenticationFilter 根据 HttpServletRequest 提取的凭证信息构建 UsernamePasswordAuthenticationToken

step2、凭证对象传递到 Authenticationmanager 进行身份认证

凭证信息传递到 AuthenticationManager 进行身份认证。

step3-1、认证失败处理逻辑
  • 借助 SecurityContextHolder 清除认证上下文信息
  • 如果配置有记住登录功能,调用:RememberMeServices.loginFail
  • 调用 AuthenticationFailureHandler

step3-2、身份认证通过
  • SessionAuthenticationStrategy 接收到新的登录通知
  • SecurityContextHolder 设置上下文信息。之后 SecurityContextPersistenceFilter 将 SecurityContext 保存到 HttpSession 中。
  • 如果配置有记住登录功能,调用:RememberMeServices.loginSuccess
  • 发布事件 InteractiveAuthenticationSuccessEvent.
  • 调用:AuthenticationSuccessHandler

2.1.2、实现:UsernamePasswordAuthenticationFilter

UsernamePasswordAuthenticationFilter 遵照抽象父类的流程。在次基础上,实现了身份凭证的获取构建身份凭证对象调用 **AuthenticationManager** 进行身份认证
相关实现代码如下:

image.png

2.2、授权:FilterSecurityInterceptor

[spring-security]-[servlet]-架构原理 - 图10

流程步骤

step1、 FilterSecurityInterceptorSecurityContextHolder 获取身份认证信息

step2、 FilterSecurityInterceptor 根据传递过来的 HttpServletRequestHttpServletResponseFilterChain 构建 FilterInvocation 对象

step3、将 FilterInvocation 传递给 SecurityMetadataSource 以获得 ConfigAttributes

step4、将 AuthenticationFilterInvocationConfigAttributes 传递给 AccessDecisionManager

step5、如果拒绝授权,则抛出 AccessDeniedException 。(默认由 ExceptionTranslationFilter 处理)

step6、如果访问被授予, FilterSecurityInterceptor 继续调用 FilterChain 剩下的过滤链。