Spring Security初见

6 篇文章 0 订阅
SpringSecurity是Spring框架的重要组成部分,提供认证、授权及攻击防护功能。它通过一系列过滤器实现安全控制,支持命令式和响应式应用。本文深入介绍了其工作原理,包括FilterChainProxy、DelegatingFilterProxy及安全过滤器的细节。
摘要由CSDN通过智能技术生成

Spring Security的作用

Spring Security是Spring全家桶里面的一个项目,提供认证、授权以及应对一般攻击的保护。凭借对命令时和响应式应用程序的一流支持,它是保护基于Spring开发的应用程序的实际标准。

即这个项目主要提供3个功能:

  • 认证 authentication
  • 授权 authorization
  • 保护 protection (一般的攻击)

介绍

Spring Security 本质上使用的是标准Servlet中的Fliter与Servlet容器集成。这意味着它可以与任何在Servlet容器中运行的任何应用一起工作。更准确地说,你可以在没有使用Spring的基于Servlet的应用中使用Spring Sercurity。

Spring Security 的大体原理是通过一个标准过滤器,进入到自己体系的过滤器中来,通过层层过滤,将攻击者的请求过滤掉。

比如最简单的用户名密码,那么就有一个org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter实现了默认的用户名密码校验。可以在该类的attemptAuthentication方法中设置断点来观察调用堆栈以追踪源码逻辑。

原理

本节可在初步搭建好工程之后再来看,会更加能理解。因为原理性的东西一般比较抽象。

回顾Filter

(图片以及表述均来自官网)

Spring Security的Servlet支持是建立在ServletFilter之上,所以可以通过回顾Filter原来对于单个HTTP请求的处理程序的流程来认识它。如下图:

Figure 1. FilterChain
客户端发送一个请求给应用程序,接着容器将创建一个包含FilterFilterChain,并且Servlet将会基于请求URI的路径处理HttpServletRequest。在一个Spring MVC应用程序中,Servlet是一个DispatcherServlet的实例。至少一个Servlet能处理单个HttpServletRequestHttpServletResponse。不管怎么样,至少一个Filter会被用于:

  • 防止下游FilterServlet被调用。在这种情况下,过滤器通常将编写HttpServletResponse
  • 修改下游FilterServlet使用的HttpServletRequestHttpServletResponse

Filter的功能来自传递给它的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会影响下游FilterServlet,因此调用每个Filter的顺序非常重要。

DelegatingFilterProxy

Spring 提供了一个Filter的实现,名字叫做DelegatingFilterProxy。它允许桥街Servlet容器的生命周期和Spring的ApplicationContext。Servlet容器允许使用自己的标准来注册Filter,但是它不知道Spring已定义的Bean。能通过标准的Servlet容器机制注册DelegatingFilterProxy,并将所有工作委托给实现了Filter接口的Spring Bean

以下是DelegatingFilterProxy如何适应FilterFilterChain

Figure 2. DelegatingFilterProxy
DelegatingFilterProxyApplicationContext中查找 Bean Filter0 ,然后调用Bean Filter0DelegatingFilterProxy的伪代码可以在下面看到。

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);
}

DelegatingFilterProxy的另一个好处是允许延迟查找Filterbean实例。这很重要,因为容器需要在容器启动之前注册Filter实例。Spring通常使用ContextLoaderListener加载 Spring Beans,这个操作会在Filter实例被注册完成之后才会完成。

FilterChainProxy

Spring Security的Servlet支持包含在FilterChainProxy中。FilterChainProxy是一个由Spring Security 提供的特别的Filter。它通过SecurityFilterChain来代理各种Filter实例。因为SecurityFilterChain是一个Bean,它是被包装在DelegatingFilterProxy中。

Figure 3. FilterChainProxy

SecurityFilterChain

FilterChainProxy使用SecurityFilterChain确定应对此请求调用哪些Spring Security过滤器。

Figure 4. SecurityFilterChain

SecurityFilterChain中的SecurityFilterChain通常是Bean,但它们是使用FilterChainProxy而不是DelegatingFilterProxy注册的。 FilterChainProxy具有直接向Servlet容器或DelegatingFilterProxy注册的优点。

首先,它为Spring Security的所有Servlet支持提供了一个起点。因此,如果您想对Spring Security的Servlet支持进行故障排除,那么可以在FilterChainProxy中添加调试点。

其次,由于FilterChainProxy对于Spring Security的使用至关重要,因此它可以执行不被视为可选任务的任务。例如,它清除SecurityContext以避免内存泄漏。它还使用Spring Security的HttpFirewall来保护应用程序免受某些类型的攻击。

此外,它在确定何时调用SecurityFilterChain时提供了更大的灵活性。在Servlet容器中,仅根据URL调用Filter。而且,FilterChainProxy可以利用RequestMatcher接口,根据HttpServletRequest中的任何内容确定调用。

实际上,FilterChainProxy可用于确定应使用哪个SecurityFilterChain。您的应用程序可以为不同的片提供完全独立的配置。

Figure 5. Multiple SecurityFilterChain

在多个SecurityFilterChain情况中,由FilterChainProxy 决定应使用哪个SecurityFilterChain。仅匹配上的第一个SecurityFilterChain将被调用。如果请求的URL是/api/messages/,则将首先在 SecurityFilterChain0/api/ **模式下进行匹配,因此即使在 SecurityFilterChainn 上也进行了匹配,也只会调用SecurityFilterChain0。如果请求的URL是/messages/,则在 SecurityFilterChain0/api/**模式下将不匹配,因此FilterChainProxy将继续尝试每个SecurityFilterChain 。假设没有其他匹配 SecurityFilterChainnSecurityFilterChain实例将被调用。

请注意,SecurityFilterChain0 仅配置了三个安全Filter实例。但是,SecurityFilterChainn 配置了四个Filter。重要的是要注意,每个SecurityFilterChain可以是唯一的,并且可以独立配置。实际上,如果应用程序希望Spring Security忽略某些请求,则SecurityFilterChain可能没有安全Filter

安全Filters

安全过滤器通过SecurityFilterChain API 被插入到FilterChainProxyFilter的顺序很重要。通常不必知道Spring Security的Filters顺序,但是,又是都了解顺序是有益的。
以下是Spring Security Filters订购的完整列表:

  • 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

处理安全异常

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

ExceptionTranslationFilter作为安全Filter之一插入到FilterChainProxy中。

在这里插入图片描述

  1. 首先,ExceptionTranslationFilter调用FilterChain.doFilter(request,response)来调用应用程序的其余部分。

  2. 如果用糊没被认证或者有一个AuthenticationException,则启动身份验证。

    • SecurityContextHolder会被清除,这个里面有已认证的信息
    • HttpServletRequest会被缓存在 RequestCache。当用户成功认证,RequestCache将会被用来重放原始请求。
    • AuthenticationEntryPoint被用来从客户端请求凭据。例如,它可能重定向到登录页面或发送WWW-Authenicate标头。
  3. 否则,如果它是AccessDeniedException,则拒绝访问。AccessDeniedHandler被调用以处理拒绝的访问。

如果应用程序未引发AccessDeniedExeption或AuthenticationException,则ExceptionTranlationFilter不执行任何操作。

ExceptionTranslationFilter的伪代码如下所示:

try {
    filterChain.doFilter(request, response); 
} catch (AccessDeniedException | AuthenticationException e) {
    if (!authenticated || e instanceof AuthenticationException) {
        startAuthentication(); 
    } else {
        accessDenied(); 
    }
}

FilterChain.doFilter(request, response)等效于调用应用程序的其余部分。这意味着如果应用程序的另一部分(即FilterSecurityInterceptor或安全方法)抛出一个AccessDeniedExceptionAuthenticationException 异常,那么它将在这里被捕获。
如果用户未被认证或者它是一个AuthenticationException,那么将会开始认证。
否则,就拒绝访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值