9. 基于servlet层面看Spring Security

本节讨论基于Servlet的应用程序中Spring Security的高级体系结构。 分3个方面介绍 Authentication(认证), Authorization(授权),Protection Against Exploits (漏洞防护) 。

9.1。复习过滤器Filters

Spring Security的Servlet支持基于Servlet Filter,因此了解Filter发挥的作用很重要。 下图显示了单个HTTP请求的处理程序的典型分层。
过滤链
在这里插入图片描述

图1. FilterChain
客户端向应用程序发送请求,然后容器创建一个 包含 Filter的FilterChain,然后 Servlet应 根据请求URI的路径处理HttpServletRequest。 在Spring MVC应用程序中, Servlet是的实例 DispatcherServlet。 大多数情况下Servlet只能处理一个 HttpServletRequest和 HttpServletResponse。 但是,不止一个 Filter可以用来:

  1. 防止下游 Filter或 Servlet调用。 在这种情况下, Filter通常会编写 HttpServletResponse。
  2. 使用下游的Filter或Servlet调用来修改HttpServletResponse。

Filter的能力是FilterChain传递给它的。

例子51. FilterChain使用例子

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
    // do something before the rest of the application
    chain.doFilter(request, response); // invoke the rest of the application
    // do something after the rest of the application
}

由于 Filter会影响 下游 Filters和 Servlet,因此Filter的调用顺序非常重要。

9.2。 DelegatingFilterProxy

Spring提供了一个叫DelegatingFilterProxy 的Filter实现 , 允许在Servlet容器的生命周期和Spring的ApplicationContext之前进行桥接。Servlet容器允许使用它自己的标准注册过滤器(Filter),但是它无法感知Spring管理的bean。 DelegatingFilterProxy可以通过标准的Servlet容器机制进行注册,但是可以将所有工作委托给实现Filter的Spring Bean。
在这里插入图片描述
图2. DelegatingFilterProxy

DelegatingFilterProxy从ApplicationContext中查找Bean Filter0,然后调用 Bean Filter0 。 DelegatingFilterProxy的伪代码 如下所示。
例子52. 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);
}

委托filterproxy的另一个好处是,它允许延迟查找过滤器bean实例。这很重要,因为容器需要在启动之前注册过滤器实例。但是,Spring通常使用ContextLoaderListener来加载Spring bean,直到需要注册过滤器实例之后才会执行。

9.3。 FilterChainProxy

Spring Security Servlet支持包含在FilterChainProxy中。FilterChainProxy是Spring Security提供的一个特殊过滤器,它允许通过SecurityFilterChain委托给许多过滤器实例。由于FilterChainProxy是一个Bean,它通常被包装在一个DelegatingFilterProxy中。
在这里插入图片描述

Figure 3. FilterChainProxy

9.4. SecurityFilterChain

FilterChainProxy使用SecurityFilterChain来确定应该为此请求调用哪个Spring Security Filter。
在这里插入图片描述

图4. SecurityFilterChain
SecurityFilterChain中的Security Filter是典型的bean,但是它们是通过FilterChainProxy注册的,而不是通过DelegatingFilterProxy。FilterChainProxy为直接注册Servlet容器或委托filterproxy提供了许多好处。首先,它为所有Spring Security 的 Servlet支持提供了一个起点。因此,如果您试图对Spring Security的Servlet支持进行故障排除,那么在FilterChainProxy中添加一个调试点是一个很好的起点。

其次,由于FilterChainProxy是使用Spring安全性的核心,所以它可以执行不被视为可选的任务。例如,它清除SecurityContext以避免内存泄漏。它还应用Spring Security的HttpFirewall来保护应用程序免受某些类型的攻击。

此外,它在决定何时应该调用SecurityFilterChain方面提供了更大的灵活性。在Servlet容器中,仅根据URL调用筛选器。然而,FilterChainProxy可以通过利用RequestMatcher接口基于HttpServletRequest中的任何内容来确定调用。

实际上,可以使用FilterChainProxy来确定应该使用哪个SecurityFilterChain。这允许为应用程序的不同部分提供完全独立的配置。
在这里插入图片描述

图5.多个SecurityFilterChain

当项目中存在多个SecurityFilterChain时,FilterChainProxy决定应使用哪个SecurityFilterChain。 仅匹配的第一个SecurityFilterChain将被调用。 如果请求的URL是/ api / messages /,则它将首先与SecurityFilterChain0的/ api / **模式匹配,因此即使SecurityFilterChainn也匹配,也只会调用SecurityFilterChain0。 如果请求的URL是/ messages/,则与SecurityFilterChain0的/ api / **模式不匹配,因此FilterChainProxy将继续尝试每个SecurityFilterChain。 假设没有其他匹配SecurityFilterChainn的SecurityFilterChain实例将被调用。

请注意,SecurityFilterChain0只配置了三个Security Filter实例。但是,SecurityFilterChainn配置了四个Security Filter。需要注意的是,每个SecurityFilterChain可以是惟一的,并且是隔离配置的。事实上,如果应用程序希望Spring security忽略某些请求,SecurityFilterChain可以没有Security Filter。

9.5。 Security Filter

使用SecurityFilterChain API将Security Filter插入到FilterChainProxy中。过滤器的顺序很重要。通常没有必要知道Spring安全过滤器的顺序。然而,有时知道顺序是有益的

以下是Spring Security过滤器顺序的完整列表:

  • ChannelProcessingFilter

  • WebAsyncManagerIntegrationFilter

  • SecurityContextPersistenceFilter

  • HeaderWriterFilter

  • CorsFilter

  • CsrfFilter

  • LogoutFilter

  • OAuth2AuthorizationRequestRedirectFilter

  • Saml2WebSsoAuthenticationRequestFilter

  • X509AuthenticationFilter

  • AbstractPreAuthenticatedProcessingFilter

  • CasAuthenticationFilter

  • OAuth2LoginAuthenticationFilter

  • Saml2WebSsoAuthenticationFilter

  • UsernamePasswordAuthenticationFilter

  • OpenIDAuthenticationFilter

  • DefaultLoginPageGeneratingFilter

  • DefaultLogoutPageGeneratingFilter

  • CompetitorSessionFilter

  • DigestAuthenticationFilter

  • BearerTokenAuthenticationFilter

  • BasicAuthenticationFilter

  • RequestCacheAwareFilter

  • SecurityContextHolderAwareRequestFilter

  • JaasApiIntegrationFilter

  • RememberMeAuthenticationFilter

  • AnonymousAuthenticationFilter

  • OAuth2AuthorizationCodeGrantFilter

  • SessionManagementFilter

  • ExceptionTranslationFilter

  • FilterSecurityInterceptor

  • SwitchUserFilter

9.6。 处理安全异常

ExceptionTranslationFilter允许将AccessDeniedException和AuthenticationException转换为HTTP响应。

ExceptionTranslationFilter插入到 FilterChainProxy 作为Security Filter之一 。
在这里插入图片描述

  1. 首先,ExceptionTranslationFilter调用FilterChain。doFilter(请求、响应)来调用处理应用程序的其余部分。

  2. 如果用户未认证或接受到AuthenticationException,就开始进入验证过程

    • SecurityContextHolder将会被清理

    • HttpServletRequest保存在RequestCache中。当用户成功进行身份验证时,将使用RequestCache重新发送原始请求。

    • AuthenticationEntryPoint用于从客户端请求凭据。例如,它可能重定向到登录页面或发送WWW-Authenticate头。

  3. 否则,如果它是AccessDeniedException,那么访问被拒绝。调用AccessDeniedHandler处理被拒绝的访问。

如果应用程序未抛出 AccessDeniedException或 AuthenticationException, ExceptionTranslationFilter则不执行任何操作。

ExceptionTranslationFilte的伪代码如下所示:

try {
    filterChain.doFilter(request, response); 
} catch (AccessDeniedException | AuthenticationException ex) {
    if (!authenticated || ex instanceof AuthenticationException) {
        startAuthentication(); 
    } else {
        accessDenied(); 
    }
}
您将回顾调用FilterChain的过滤器。doFilter(请求、响应)相当于调用应用程序的其余部分。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值