14. Core Security Filters(核心安全过滤器)

在使用Spring Security的web应用程序中,总会用到一些关键的过滤器,所以我们首先来看看这些过滤器及其支持类和接口。我们不会涵盖所有特性,所以如果你想了解完整的情况,一定要看看Javadoc。

14.1 FilterSecurityInterceptor(过滤器安全性拦截器)

在讨论一般的访问控制时,我们已经简要地看到了FilterSecurityInterceptor,并且我们已经将它与< intercept-url >元素组合在一起的命名空间一起使用,以便在内部进行配置。现在,我们将看到如何显式地配置它,以便与FilterChainProxy及其伴随的过滤器ExceptionTranslationFilter一起使用。典型的配置示例如下所示:

 


 

FilterSecurityInterceptor负责处理HTTP资源的安全性。它需要对授权管理器和访问决策管理器的引用。它还提供了适用于不同的HTTP URL请求的配置属性。请参考技术介绍中关于这些内容的原始讨论。

FilterSecurityInterceptor可以通过两种方式配置配置属性。如上所示,第一个是使用<filter-security-metadata-source>命名空间元素。这类似于命名空间一章中的< http >元素,但是<拦截url >子元素只使用pattern 和access 属性。逗号用于分隔应用于每个HTTP URL的不同配置属性。第二种选择是编写自己的SecurityMetadataSource,但这超出了本文的范围。不管使用什么方法,SecurityMetadataSource负责返回一个列表< ConfigAttribute >,该列表包含与单个安全HTTP URL相关联的所有配置属性。

应该注意的是,FilterSecurityinterceptor . SetSecurityMetadataSource()方法实际上需要FilterInvocationSecurityMetadataSource的一个实例。这是一个标记接口,它子类化了SecurityMetadataSource。它只是表示安全数据源(SecurityMetadataSource ),可以理解为过滤器调用(FilterInvocation )。为了简单起见,我们继续将过滤器调用安全数据源(FilterInvocationSecurityMetadataSource )称为安全数据源(SecurityMetadataSource),因为这种区别与大多数用户没有多大关系。

由命名空间语法创建的SecurityMetadataSource通过将请求URL与配置的模式属性进行匹配来获取特定过滤器调用的配置属性。这与命名空间配置的行为方式相同。默认情况下,将所有表达式视为Apache Ant路径,对于更复杂的情况,也支持正则表达式。请求匹配器属性用于指定使用的模式类型。不能在同一个定义中混合使用表达式语法。例如,前面使用正则表达式而不是ant路径的配置如下:

 


 

模式总是按照它们被定义的顺序被评估。因此,重要的是在列表中更高的位置定义更具体的模式,而不是更不具体的模式。这反映在我们上面的例子中,其中/secure/super/模式看起来比不太具体/secure/模式高。如果颠倒过来,则/secure/模式将始终匹配,并且/secure/super/模式将永远不会被评估。

14.2 ExceptionTranslationFilter(异常转换过滤器)

ExceptionTranslationFilter 位于安全筛选器堆栈中的FilterSecurityInterceptor 接口之上。它本身不执行任何实际的安全强制,但是处理由安全拦截器引发的异常,并提供合适的HTTP响应。

 


 

14.2.1 AuthenticationEntryPoint(认证点)

如果用户请求一个安全的HTTP资源,但没有经过身份验证,将调用AuthenticationEntryPoint。一个适当的AuthenticationException或AccessDeniedException将被调用堆栈中的安全拦截器抛出,触发入口点上的开始方法。这样做的工作是向用户提供适当的响应,以便开始身份验证。我们在这里使用的是LoginUrlAuthenticationEntryPoint,它将请求重定向到不同的URL(通常是登录页面)。实际使用的实现将取决于您希望在应用程序中使用的身份验证机制。

14.2.2 AccessDeniedHandler(拒绝访问处理程序)

如果用户已经通过身份验证,并试图访问受保护的资源,会发生什么情况?在正常使用中,这不应该发生,因为应用程序工作流应该被限制在用户可以访问的操作范围内。例如,指向管理页面的HTML链接可能对没有管理员角色的用户隐藏。但是你不能依靠隐藏链接来保证安全,因为总有一种可能是用户直接输入网址来试图绕过限制。或者,他们可能会修改一个RESTful URL来更改一些参数值。您的应用程序必须针对这些情况进行保护,否则肯定不安全。您通常会使用简单的web层安全性来对基本的URL应用约束,并在服务层接口上使用更具体的基于方法的安全性来确定什么是允许的。

如果抛出了AccessDeniedException,并且用户已经过身份验证,则这意味着已经尝试了他们没有足够权限的操作。在这种情况下,ExceptionTranslationFilter将调用第二个策略,AccessDeniedHandler。默认情况下,使用AccessDeniedHandlerImpl,它只向客户端发送403(禁止)响应。或者,您可以显式地配置一个实例(如上面的例子),并设置一个错误页面URL,它会将请求转发。这可以是一个简单的“拒绝访问”页面,比如一个JSP,也可以是一个更复杂的处理程序,比如一个MVC控制器。当然,您可以自己实现接口,并使用自己的实现。

当您使用命名空间来配置应用程序时,还可以提供自定义的AccessDeniedHandler。有关更多详细信息,请参见命名空间附录。

14.2.3 SavedRequest s and the RequestCache Interface(保存请求和请求缓存接口)

ExceptionTranslationFilter职责的另一个职责是在调用AuthenticationEntryPoint之前保存当前请求。这允许在用户进行身份验证后恢复请求(参见前面的web身份验证 web authentication概述)。然后通过默认的SavedRequestAwareAuthenticationSuccessHandler重定向到原始的URL(见下文below)。

RequestCache封装了存储和检索HttpServletRequest实例所需的功能。默认情况下,使用HttpSessionRequestCache,它将请求存储在HttpSession中。当用户被重定向到原始网址时,RequestCacheFilter 的工作是从缓存中实际恢复保存的请求。

在正常情况下,您不需要修改任何此类功能,但是保存请求处理是一种“尽力而为”的方法,并且可能存在默认配置无法处理的情况。从Spring Security 3.0开始,这些接口的使用使其完全可插拔。

14.3 SecurityContextPersistenceFilter(安全性上下文持久性过滤器)

我们在“技术概述”一章中介绍了这一非常重要的过滤器的用途,因此您可能需要在此时重新阅读该部分。让我们先来看一下您将如何配置它以与FilterChainProxy一起使用。基本配置只需要bean本身

 


 

正如我们前面看到的,这个过滤器有两个主要任务。它负责存储HTTP请求之间的安全上下文内容(securitycontext ),并在请求完成时清除安全上下文持有者(SecurityContextHolder )。清除ThreadLocal其中存储的上下文是必不可少的,因为它可能会以其他方式可能是一个线程被替换成servlet容器的线程池,仍连接一个特定的用户的安全上下文。这个线程可能在稍后的阶段中使用,与错误的凭证执行操作。

14.3.1 SecurityContextRepository(安全性整合存储)

从Spring Security 3.0开始,加载和存储安全上下文的任务现在被委托给一个单独的策略接口:

 


 

HttpRequestResponseHolder只是传入请求和响应对象的容器,允许实现用包装类替换它们。返回的内容将被传递给过滤器链。默认实现是HttpsessionsEcurityContextRepository,它将安全上下文存储为HttpSession属性。这个实现中最重要的配置参数是allowSessionCreation属性,它默认为true,因此允许类创建一个会话,如果它需要一个会话来存储经过身份验证的用户的安全上下文(除非已经进行了身份验证并且安全上下文的内容已经更改,否则它不会创建一个会话)。如果不希望创建会话,则可以将此属性设置为false:

 


 

或者,您可以提供一个NullSecurityContextRepository实例,一个空对象实现,这将阻止存储安全上下文,即使在请求期间已经创建了一个会话。

14.4 UsernamePasswordAuthenticationFilter(用户名密码验证过滤器)

我们现在已经看到了三个主要的过滤器,它们总是出现在Spring Security web配置中。这三个也是由namespace <http >元素自动创建的,不能被替换。现在唯一缺少的是一种真正的认证机制,一种允许用户进行认证的机制。该过滤器是最常用的身份验证过滤器,也是最常用的定制过滤器,它还提供了命名空间中的< form-login >元素使用的实现。配置它需要三个阶段。

        用登录页面的URL配置一个LoginUrlAuthenticationEntryPoint,就像我们上面做的那样,并在异常转换过滤器上设置它。

        实现登录页面(使用JSP或MVC控制器)。

        在应用程序上下文中配置一个UsernamePasswordAuthenticationFilter实例。

        将过滤器bean添加到您的过滤器链代理(确保你要注意顺序)。

登录表单只包含用户名和密码输入字段,并发布到由过滤器监控的网址(默认情况下是/login)。基本过滤器配置如下所示:

 


 

14.4.1 Application Flow on Authentication Success and Failure(认证成功和失败的应用流程)

过滤器调用配置的身份验证管理器AuthenticationManager 来处理每个身份验证请求。成功身份验证或身份验证失败后的目标分别由身份验证成功处理程序AuthenticationSuccessHandler 和身份验证失败处理程序AuthenticationFailureHandler 策略接口控制。过滤器具有允许您设置这些属性的属性,因此您可以完全自定义行为。提供了一些标准实现,如SimpleurlAuthenticationSuccessHandler、SavedRequestAwareauthenticationSuccessHandler、SimpleurlAuthenticationFailureHandler、ExceptionMapingAuthenticationFailureHandler和DelegatingauthenticationFailureHandler。查看这些类的Javadoc以及抽象认证处理过滤器,了解它们的工作方式和支持的特性。

如果身份验证成功,生成的身份验证对象将被放入SecurityContextHolder。配置的AuthenticationSuccessHandler将被重定向或用户转发给适当的目的地。默认情况下,使用savedrequestawareuthenticationsuccesshandler,这意味着在要求用户登录之前,用户将被重定向到他们请求的原始目标。

ExceptionTranslationFilter缓存用户发出的原始请求。当用户进行身份验证时,请求处理程序利用这个缓存的请求来获取原始的网址并重定向到它。然后,原始请求被重建并用作替代。

如果身份验证失败,则将调用AuthenticationFailureHandler配置。

我们使用了一个转发,这样SecurityContextHolder仍然包含主体的详细信息,这对于向用户显示可能很有用。在旧版本的Spring Security中,我们依赖servlet容器来处理403错误消息,它缺少有用的上下文信息。

在Spring Security 2.0和更早的版本中,这个过滤器被称为httpessioncontextintegrationfilter,它执行的所有存储上下文的工作都是由过滤器本身执行的。如果您熟悉这个类,那么现在大多数可用的配置选项都可以在httpassionsecuritycontextrepository上找到。

出于历史原因,在Spring Security 3.0之前,此筛选器称为AuthenticationProcessingFilter,入口点称为AuthenticationProcessingFilterEntryPoint。由于该框架现在支持许多不同形式的身份验证,所以在3.0中它们都被赋予了更具体的名称。

在3.0之前的版本中,此时的应用程序流已经发展到了由这个类和策略插件的混合属性控制的阶段。3.0决定重构代码,使这两个策略完全负责。

 

posted @ 2020-08-16 17:19  节日快乐  阅读(231)  评论(0编辑  收藏  举报