本文主要评论下 Spring Web 运用相关的 Spring Security 架构。

1.Servlet Filter 回顾

Spring Security 是基于 Servlet Filter 的。所以先大致了解一下 Filter 的作用是有协助的。下图显示了处理单个 HTTP 恳求的程序的典型分层。

Spring Security 架构

客户端向服务发送恳求,Web 容器创立一个 FilterChain 实例,该实例包括一组 Filter,以及一个Servlet。Servlet 依据恳求途径处理来处理 HttpServletRequest。在 Spring MVC 运用中,Servlet 是 DispatcherServlet.最多只有一个 Servlet能够处理单个 HttpServletRequest 和HttpServletResponse。可是能够有多个Filter来履行以下逻辑:

  • 阻止后续的 Filter 或 Servlet 被调用。在这种情况下,Filter 一般负责结构HttpServletResponse 呼应客户端.
  • 修改 HttpServletRequest 或许 HttpServletResponse 内容

由于 Filter 是按次序处理恳求,因此次序对于正确完成一个恳求的处理是非常重要。

2.DelegatingFilterProxy

Spring 供给了一个Filter名为DelegatingFilterProxy的完成。这个 Servet 在 Servlet 容器的生命周期和 Spring 的 ApplicationContext 之间建立了桥接。Servlet 容器用自己的规范注册 Filter,但它对 Spring Bean 无感知。DelegatingFilterProxy 经过规范 Servlet 容器机制注册到 Servlet 中,但将所有作业都托付给了完成 Filter 的 Spring Bean。

下图展示了 DelegatingFilterProxy 在 Filter 和 FilterChain 架构中方位:

Spring Security 架构

DelegatingFilterProxy 从 Spring 容器 ApplicationContext 中查找 Bean Filter,然后调用。DelegatingFilterProxy 伪代码如下所示:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
	// Lazily get Filter that was registered as a Spring Bean
	// For the example in DelegatingFilterProxy, delegate is an instance of Bean Filter0
	Filter delegate = getFilterBean(someBeanName);
	// delegate work to the Spring Bean
	delegate.doFilter(request, response);
}

3.FilterChainProxy

Spring Security 对 Servlet 的支持包括在 FilterChainProxy。FilterChainProxy 是 Spring Security 供给的一个特别的 Filter。它经过过滤功用署理给 SecurityFilterChain 维护的一组 Filter 链。

Spring Security 架构

4.SecurityFilterChain

FilterChainProxy 运用 SecurityFilterChain 来确认应该为一个恳求调用哪些 Spring Security 的 Filter。

Spring Security 架构

SecurityFilterChain 中的 Filter 是 Spring Bean。它们是注册 FilterChainProxy 中,而不是在 DelegatingFilterProxy 注册的。相比较直接向 Servlet 容器或 DelegatingFilterProxy 注册,FilterChainProxy 有许多优势。

  • 首要,它为 Spring Security 供给了一个起点。假如您尝试对 Spring Security 进行毛病 debug,那么在 FilterChainProxy 是个合适调试断点。

  • 其次,由于 FilterChainProxy 是 Spring Security 的核心,它能够履行一些关键使命。例如,它能够铲除 SecurityContext 以防止内存走漏。它还能够用 Spring Security HttpFirewall 来保护运用免受某些类型的攻击。

  • 此外,它在确认何时调用一个 SecurityFilterChain 方面供给了更大的灵活性。在 Servlet 容器中,Filter 只能依据 URL 形式匹配调用。可是,FilterChainProxy 能够运用 RequestMatcher 来匹配 HttpServletRequest 中任何内容来调用。

FilterChainProxy 能够确认调用哪个 SecurityFilterChain。咱们能够运用这个特性为运用的不同部分供给完全独立的装备。

Spring Security 架构

上图有多个 SecurityFilterChain, FilterChainProxy 决定应该运用哪个 SecurityFilterChain。第一个匹配的 SecurityFilterChain 会被调用。假如恳求 URL 是/api/messages/,它将首要匹配上第一个SecurityFilterChain SecurityFilterChain0 的/api/** 形式,尽管 第 n 个 SecurityFilterChain 也能够匹配上 SecurityFilterChain0 是第一个匹配的。因此,SecurityFilterChain0 会被调用。

请注意,上图中 SecurityFilterChain0 仅装备了三个 security Filter 实例。而 第 n 个SecurityFilterChain 装备了四个 security Filter 实例。重要的是要注意,每个 SecurityFilterChain 都可所以唯一的而且能够独自装备。实际上,假如运用程序期望 Spring Security 忽略某些恳求,则能够不给 个SecurityFilterChain 装备 security Filter 实例。

5.Security Filters

Security Filter 是经过 SecurityFilterChainAPI 被插入到 FilterChainProxy 中的。Filter 的次序是有意义的。一般咱们不需要知道 Spring Security Filter 的次序。可是,有时知道排序是有利的。

以下是 Spring Security Filter 按次序的完整列表:

  • ForceEagerSessionCreationFilter
  • ChannelProcessingFilter
  • WebAsyncManagerIntegrationFilter
  • SecurityContextPersistenceFilter
  • HeaderWriterFilter
  • CorsFilter
  • CsrfFilter
  • LogoutFilter
  • OAuth2AuthorizationRequestRedirectFilter
  • Saml2WebSsoAuthenticationRequestFilter
  • X509AuthenticationFilter
  • AbstractPreAuthenticatedProcessingFilter
  • CasAuthenticationFilter
  • OAuth2LoginAuthenticationFilter
  • Saml2WebSsoAuthenticationFilter
  • UsernamePasswordAuthenticationFilter
  • OpenIDAuthenticationFilter
  • DefaultLoginPageGeneratingFilter
  • DefaultLogoutPageGeneratingFilter
  • ConcurrentSessionFilter
  • DigestAuthenticationFilter
  • BearerTokenAuthenticationFilter
  • BasicAuthenticationFilter
  • RequestCacheAwareFilter
  • SecurityContextHolderAwareRequestFilter
  • JaasApiIntegrationFilter
  • RememberMeAuthenticationFilter
  • AnonymousAuthenticationFilter
  • OAuth2AuthorizationCodeGrantFilter
  • SessionManagementFilter
  • ExceptionTranslationFilter
  • FilterSecurityInterceptor
  • SwitchUserFilter

6.处理安全反常

ExceptionTranslationFilter 是Srping Security 供给的一个 Filter。ExceptionTranslationFilter 能够将 AccessDeniedException 和 AuthenticationException 转换为 HTTP 呼应。

Spring Security 架构

  • 首要,ExceptionTranslationFilter调用 FilterChain.doFilter(request, response) 来调用履行运用的其余部分。

  • 假如用户未经过身份验证或遇到了一个 AuthenticationException 反常,则开端身份验证

    • 铲除 SecurityContextHolder
    • 将 HttpServletRequest 保存在 RequestCache 中。当用户成功认证后,RequestCache 将被用于重放原始恳求。
    • AuthenticationEntryPoint 用于从客户端获取凭据。例如,它可能会将用户重定向到登录页面或发送 WWW-Authenticate 恳求头。
  • 假如是 AccessDeniedException,则拒绝拜访。AccessDeniedHandler 会被调用来处理拒绝拜访。

假如运用程序没有抛出 AccessDeniedException 反常或 AuthenticationException 反常,ExceptionTranslationFilter 则不履行任何操作。

ExceptionTranslationFilter 的伪代码如下所示:

try {
	filterChain.doFilter(request, response);    //1
} catch (AccessDeniedException | AuthenticationException ex) {
	if (!authenticated || ex instanceof AuthenticationException) {
		startAuthentication();              //2
	} else {
		accessDenied();                     //3
	}
}
    1. filterChain.doFilter(request, response) 表明继续履行恳求处理,假如处理过程中有抛出一个 AuthenticationException 或许 AccessDeniedException 反常,反常将会被捕获和处理。
    1. 假如用户没有做过身份验证,或许发生了 AuthenticationException 反常,则开开端身份验证逻辑
    1. 否则履行拒绝拜访逻辑

  • 我正在参加技术社区创作者签约计划招募活动,点击链接报名投稿。