`
lengyun3566
  • 浏览: 452543 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
D59180b9-02f1-3380-840c-ea34da46143c
《Spring Secur...
浏览量:383426
社区版块
存档分类
最新评论

《Spring Security3》第二章第三部分翻译(上)

阅读更多

 

安全的复杂之处:安全web请求的架构

         借助于Spring Security的强大基础配置功能以及内置的认证功能,我们在前面讲述的三步配置是很快就能完成的;它们的使用是通过添加auto-config属性和http元素实现的。

         但不幸的是,应用实现的考量、架构的限制以及基础设施集成的要求可能使你的Spring Security实现远较这个简单的配置所提供的复杂。很多用户一使用比基本配置复杂的功能就会遇到麻烦,那是因为他们不了解这个产品的架构以及各个元素是如何协同工作以实现一个整体的。

         理解web请求的整体流程以及它们是如何穿越实现功能的拦截器链,对我们成功了解Spring Security的高级话题至关重要。记住认证和授权的基本概念,因为它们贯穿我们要保护的系统架构的始终。


请求是怎样被处理的?

         Spring Security的架构在很大程度上依赖代理(delegates)和servlet过滤器,来实现环绕在web应用请求前后的功能层。

         Servlet过滤器(Servlet Filter,实现javax.servlet.Filter接口的类)被用来拦截用户请求来进行请求之前或之后的处理,或者干脆重定向这个请求,这取决于servlet过滤器的功能。在JBCP Pets在线商店中,最终的目标servletSpring MVC 分发servlet,但是在理论上它可能是任何一个web servlet。下面的图描述了一个servlet过滤器是如何封装一个用户请求的:



 Spring SecurityXML配置文件中的自动配置属性,建立了十个servlet过滤器,它们通过使用Java EEservlet过滤器链按顺序组合起来。Filter chainJava EE Servlet API的一个概念,通过接口javax.servlet.FilterChain进行定义,它允许在web应用中的一系列的servlet过滤器能够应用于任何给定的请求。

         与生活中金属制定的链类似,每一个servelt过滤器代表链上的一环,它会进行方法的调用以处理用户的请求。请求穿过整个过滤器链,按顺序调用每个过滤器。



 正如你能从链这个词汇中推断出的那样,servlet请求按照一定的顺序从一个过滤器到下一个穿过整个过滤器链,最终到达目标servlet。与之相对的是,当servelt处理完请求并返回一个response时,过滤器链按照相反的顺序再次穿过所有的过滤器。

         Spring Security使用了过滤器链的概念并实现了自己抽象,提供了VirtualFilterChain,它可以根据Spring Security XML配置文件中设置的URL模式动态的创建过滤器链(可以将它与标准的Java EE过滤器链进行对比,后者需要在web应用的部署描述文件中进行设置)。

Servlet过滤器除了能够如它的名字所描述的那样进行过滤功能(或阻止请求)以外,还可以用于很多其他的目的。实际上,很多的servlet过滤器的功能类似于在web运行的环境中对请求进行AOP式的代理拦截,因为它们可以允许一些功能在任何发往servelt容器的请求处理之前或之后执行。过滤器能实现的多功能在Spring Security中页得到了体现,因为很多过滤器实际上并不直接影响用户的请求。】

 

自动配置的选项为你建立了十个Spring Security的过滤器。理解这些过滤器的默认行为以及它们在哪里以及如何配置的,对使用Spring Security的高级功能至关重要。

 

这些过滤器以及它们使用的顺序,在下面的表格中进行了描述。大多数这些过滤器在我们完善JBCP Pets在线商店的过程中都会被再次提到,所以如果你现在不明白它们的确切功能也不必担心。

过滤器名称

描述

o.s.s.web.context.SecurityContextPersistenceFilter

负责从SecurityContextRepository获取或存储SecurityContextSecurityContext代表了用户安全和认证过的session

o.s.s.web.authentication.logout.LogoutFilter

监控一个实际为退出功能的URL(默认为/j_spring_security_logout),并且在匹配的时候完成用户的退出功能。

o.s.s.web.authentication.UsernamePasswordAuthenticationFilter

监控一个使用用户名和密码基于form认证的URL(默认为/j_spring_security_check),并在URL匹配的情况下尝试认证该用户。

o.s.s.web.authentication.ui.DefaultLoginPageGeneratingFilter

监控一个要进行基于fornOpenID认证的URL(默认为/spring_security_login),并生成展现登录formHTML

o.s.s.web.authentication.www.BasicAuthenticationFilter

监控HTTP 基础认证的头信息并进行处理

o.s.s.web.savedrequest.

RequestCacheAwareFilter

用于用户登录成功后,重新恢复因为登录被打断的请求。

o.s.s.web.servletapi.

SecurityContextHolderAwareRequest

Filter

用一个扩展了HttpServletRequestWrapper的子类(o.s.s.web. servletapi.SecurityContextHolderAwareRequestWrapper)包装HttpServletRequest。它为请求处理器提供了额外的上下文信息。

o.s.s.web.authentication.

AnonymousAuthenticationFilter

如果用户到这一步还没有经过认证,将会为这个请求关联一个认证的token,标识此用户是匿名的。

o.s.s.web.session.

SessionManagementFilter

根据认证的安全实体信息跟踪session,保证所有关联一个安全实体的session都能被跟踪到。

o.s.s.web.access.

ExceptionTranslationFilter

解决在处理一个请求时产生的指定异常

o.s.s.web.access.intercept.

FilterSecurityInterceptor

简化授权和访问控制决定,委托一个AccessDecisionManager完成授权的判断

Spring Security拥有总共大约25个过滤器,它们能够根据你的需要进行适当的应用以改变用户请求的行为。当然,如果需要的话,你也可以添加你自己实现了javax.servlet.Filter接口的过滤器。

请记住,如果你在XML配置文件中使用了auto-config属性,以上表格中列出的过滤器自动添加的。通过使用一些额外的配置指令,以上列表中的过滤器能够精确的控制是否被包含,在后续的章节章将会进行介绍。

 

你可能会完全从头做起来配置过滤器链。尽管这会很单调乏味,因为有很多的依赖关系要配置,但是它为配置和应用场景的匹配方面提供了更高层次的灵活性。我们将在第六章讲述在启动的过程中所依赖的Spring Bean的声明。

你可能想知道DelegatingFilterProxy是怎样找到Spring Security配置的过滤器链的。让我们回忆一下,在web.xml文件中,我们需要给DelegatingFilterProxy一个过滤器的名字:

<filter>

  <filter-name>springSecurityFilterChain</filter-name>

  <filter-class>

    org.springframework.web.filter.DelegatingFilterProxy

  </filter-class>

</filter>

这个过滤器的名字并不是随意配置的,实际上会跟根据这个名字把Spring Security织入到DelegatingFilterProxy。除非明确配置,否则DelegatingFilterProxy会在Spring WebApplicationContext中寻找同名的配置bean(名字是在filter-name中指明的)。更多配置DelegatingFilterProxy的细节可以在这个类对应的Javadoc中找到。

auto-config场景下,发生了什么事情?

Spring Security 3中,使用auto-config会自动提供以下三个认证相关的功能:

<!--[if !supportLists]-->l  <!--[endif]-->HTTP基本认证

<!--[if !supportLists]-->l  <!--[endif]-->Form登录认证

<!--[if !supportLists]-->l  <!--[endif]-->退出

值得注意的是,也可以使用配置元素实现这三个功能,能够实现比使用auto-config提供的功能更精确。我们将在随后的章节中看到它们的使用以提供更高级的功能。

auto-config和以前不一样了!在Spring Security3之前的版本中,auto-config属性提供了比现在更多的启动项。在Spring Security2中通过auto-config配置的功能,现在可以使用security命名空间样式的配置很容易的实现。请参考13章:迁移至Spring Security 3来获取更多从Spring Security2迁移到3的详细信息。】

除了以上认证相关的功能,其它过滤器链的配置是通过使用<http>元素来实现的。

 

用户是怎样认证的?

在我们的安全系统中,当一个用户在我们的登录form中提供凭证后,这些凭证信息必须与凭证存储中的数据进行校验以确定下一步的行为。凭证的校验涉及到一系列的逻辑组件,它们封装了认证过程。

我们将会深入讲解我们例子中的用户名和密码登录form,与之对应的接口和实现都是特定于用户名和密码认证的。但是,请记住,整体的认证是相同的,不管你是使用基于form的登录请求,或者使用一个外部的认证提供者如集中认证服务(CAS),抑或用户的凭证信息存在一个数据库或在一个LDAP目录中。在本书的第二部分,我们将会看到在基于form登录中学到的概念是如何应用到更高级的认证机制中。

涉及到认证功能的重要接口在下边的图标中有一个概览性的描述:



 站在一个较高层次上看,你可以看到有三个主要的组件负责这项重要的事情:

接口名

描述/角色

AbstractAuthenticationProcessingFilter

它在基于web的认证请求中使用。处理包含认证信息的请求,如认证信息可能是form POST提交的、SSO信息或者其他用户提供的。创建一个部分完整的Authentication对象以在链中传递凭证信息。

AuthenticationManager

它用来校验用户的凭证信息,或者会抛出一个特定的异常(校验失败的情况)或者完整填充Authentication对象,将会包含了权限信息。

AuthenticationProvider

它为AuthenticationManager提供凭证校验。一些AuthenticationProvider的实现基于凭证信息的存储,如数据库,来判定凭证信息是否可以被认可。

有两个重要接口的实现是在认证链中被这些参与的类初始化的,它们用来封装一个认证过(或还没有认证过的)的用户的详细信息和权限。

o.s.s.core.Authentication是你以后要经常接触到的接口,因为它存储了用户的详细信息,包括唯一标识(如用户名)、凭证信息(如密码)以及本用户被授予的一个或多个权限(o.s.s.core.

GrantedAuthority)。开发人员通常会使用Authentication对象来获取用户的详细信息,或者使用自定义的认证实现以便在Authentication对象中增加应用依赖的额外信息。

以下列出了Authentication接口可以实现的方法:

方法签名

描述

Object getPrincipal()

返回安全实体的唯一标识(如,一个用户名)

Object getCredentials()

返回安全实体的凭证信息

List<GrantedAuthority>

getAuthorities()

得到安全实体的权限集合,根据认证信息的存储决定的。

Object getDetails()

返回一个跟认证提供者相关的安全实体细节信息

你可能会担心的发现,Authentication接口有好几个方法的返回值是简单的java.lang.Object。这可能会导致在编译阶段很难知道调用Authentication对象的方法返回值是什么类型的对象。

需要注意的一点是AuthenticationProvider并不是直接被AuthenticationManager接口使用或引用的。但是Spring Security只提供了AuthenticationManager的一个具体实现类,即o.s.s.authentication.ProviderManager,它会使用一个或更多以上描述的AuthenticationProvider实现类。因为AuthenticationProvider的使用非常普遍并且被很好的集成在ProviderManager中,所以理解它在最常见的基本配置下是如何工作的就非常重要了。

让我们更仔细的看看在基于web用户名和密码认证的请求下,这些类的处理过程:

 

 



 
让我们看一下在较高层次示意图中反映出的抽象工作流程,并将其细化到这个基于表单认证的具体实现。你可以看到UsernamePasswordAuthenticationFilter负责(通过代理从它的抽象父类中)创建UsernamePasswordAuthenticationToken对象(Authentication接口的一个实现),并部分填充这个对象依赖的信息,这些信息来自HttpServletRequet。但是它是从哪里获取用户名和密码的呢?

spring_security_login是什么?我们怎么到达这个界面的?

 你可能已经发现,当你试图访问我们JBCP Pets商店的主页时,你被重定向到http://localhost:8080/JBCPPets/spring_security_login



 URLspring_security_login部分表明这是一个默认的登录的页面并且是在DefaultLoginPageGeneratingFilter中命名的。我们可以使用配置属性来修改这个页面的名字从而使得它对于我们应用来说是唯一的。

【建议修改登录页URL的默认值。修改后不仅能够对应用或搜索引擎更友好,而且能够隐藏你使用Spring Security作为安全实现的事实。通过这种方式来掩盖Spring Security能够使得万一Spring Security被发现存在安全漏洞时,恶意黑客寻找你应用漏洞的难度。尽管通过这种方式的安全掩盖不会降低你应用的脆弱性,但是它确实能够使得一些传统的黑客工具很难确定你的应用能够承担的住什么类型的攻击。需要注意的是,这里并不是“spring”名称在URL中出现的唯一地方。我们将在后面的章节详细阐述。】

让我们看一下这个formHTML源码(忽略布局信息),来看一下UsernamePasswordAuthenticationFilter期望得到的信息:

 

<form name='f' action='/JBCPPets/j_spring_security_check'  method='POST'>

  User:<input type='text' name='j_username' value=''>

  Password:<input type='password' name='j_password'/>

  <input name="submit" type="submit"/>

  <input name="reset" type="reset"/>

</form>

你可以看到用户名和密码对应的form文本域有独特的名字((j_usernamej_password),并且formaction地址j_spring_security_check也并不是我们配置的。它们是怎么来的呢?

文本域的名字是UsernamePasswordAuthenticationFilter规定的,并借鉴了Java EE Servlet 2.x的规范(在SRV.12.5.3章节中),规范要求登录的form使用特定的名字并且formaction要为特定的j_security_check值。这样的实际模式目标是允许基于Java EE servlet-based的应用能够与servlet容器的安全设施以标准的方式连接起来。

因为我们的应用没有使用到servlet容器的安全组件,所以可以明确设置UsernamePasswordAuthenticationFilter以使得文本域有不同的名字。这种特定的配置变化可能会比你想象的复杂。现在,我们将要回顾一下UsernamePasswordAuthenticationFilter的生命周期,看一下它是如何进入我们配置的(尽管我们将会在第六章再次讲述这个配置)。

UsernamePasswordAuthenticationFilter是通过<http>配置指令的<form-login>子元素来进行配置的。正如在本章前面讲述的,我们设置的auto-config元素将会在你没有明确添加的情况下包含了<form-login>功能。正如你可能猜测的那样,j_spring_security_check并不对应任何应用中的物理资源。它只是UsernamePasswordAuthenticationFilter监视的一个基于form登录的URL。实际上,在Spring Security中有好几个这样的特殊的URL来实现特定的全局功能。你能在附录:参考资料中找到这些URL的一个列表。

 

用户的凭证信息是在哪里被校验的?

在我们的简单的三步配置文件中,我们使用了一个基于内存的凭证存储实现快速的部署和运行:

 

<authentication-manager alias="authenticationManager">

  <authentication-provider>

    <user-service>

      <user authorities="ROLE_USER" name="guest" password="guest"/>

    </user-service>

  </authentication-provider>

</authentication-manager>

我们没有将AuthenticationProvider与任何具体的实现相关联,在这里我们再次看到了security命名空间默认为我们做了许多机械的配置工作。但是需要记住的是AuthenticationManager支持配置一个或多个AuthenticationProvider<authentication-provider>声明默认谁实例化一个内置的实现,即o.s.s.authentication.dao.DaoAuthenticationProvider<authentication-provider>声明会自动的将这个AuthenticationProvider对象织入到配置的AuthenticationManager中,当然在我们这个场景中AuthenticationManager是自动配置的。

DaoAuthenticationProviderAuthenticationProvider的简单封装实现并委托o.s.s.core.userdetails.UserDetailsService接口的实现类进行处理。UserDetailsService负责返回o.s.s.core.userdetails.UserDetails的一个实现类。

如果你查看UserDetailsJavadoc,你会发现它与我们前面讨论的Authentication接口非常类似。尽管它们在方法名和功能上有些重叠的部分,但是请不要混淆,它们有着截然不同的目的:

接口

目的

Authentication

它存储安全实体的标识、密码以及认证请求的上下文信息。它还包含用户认证后的信息(可能会包含一个UserDetails的实例)。通常不会被扩展,除非是为了支持某种特定类型的认证。

UserDetails

为了存储一个安全实体的概况信息,包含名字、e-mail、电话号码等。通常会被扩展以支持业务需求。

我们对<user-service>子元素的声明将会触发对o.s.s.core.userdetails.memory.InMemoryDaoImpl的配置,它是UserDetailsService的一个实现。正如你可能期望的那样,这个实现将在安全XML文件中配置的用户信息放在一个内存的数据存储中。这个service的实现支持其它属性的设置,从而实现账户的禁用和锁定。

让我们更直观的看一下DaoAuthenticationProvider是如何交互的,从而AuthenticationManager提供认证支持:



 正如你可能想象的那样,认证是相当可配置化的。大多数的Spring Security例子要么使用基于内存的用户凭证存储要么使用JDBC(在数据库中)的用户凭证存储。我们已经意识到修改JBCP Pets应用以实现数据库存储用户凭证是一个好主意,我们将会在第四章来处理这个配置变化。

什么时候校验不通过?

Spring Security很好的使用应用级异常(expected exceptions)来表示处理各种的结果情况。你可能在使用Spring Security的日常工作中不会与这些异常打交道,但是了解它们以及它们为何被抛出将会在调试问题或理解应用流程中非常有用。

所有认证相关的异常都继承自o.s.s.core.AuthenticationException基类。除了支持标准的异常功能,AuthenticationException包含两个域,可能在提供调试失败信息以及报告信息给用户方面很有用处。

<!--[if !supportLists]-->l  <!--[endif]-->authentication:存储关联认证请求的Authentication实例;

<!--[if !supportLists]-->l  <!--[endif]-->extraInformation:根据特定的异常可以存储额外的信息。如UsernameNotFoundException在这个域上存储了用户名。

我们在下面的表格中,列出了常见的异常。完整的认证异常列表可以在附录:参考资料中找到:

异常类

何时抛出

extraInformation内容

BadCredentialsException

如何没有提供用户名或者密码与认证存储中用户名对应的密码不匹配

UserDetails

LockedException

如果用户的账号被发现锁定了

UserDetails

UsernameNotFoundException

如果用户名不存在或者用户没有被授予的GrantedAuthority

String(包含用户名)

这些以及其他的异常将会传递到过滤器链上,通常将会被request请求的过滤器捕获并处理,要么将用户重定向到一个合适的界面(登录或访问拒绝),要么返回一个特殊的HTTP状态码,如HTTP 403(访问被拒绝)。

 

 

  • 大小: 48.6 KB
  • 大小: 23.8 KB
  • 大小: 23.9 KB
  • 大小: 76.2 KB
  • 大小: 57.7 KB
  • 大小: 34.3 KB
  • 大小: 53.7 KB
9
0
分享到:
评论
8 楼 ITCEO1 2016-04-05  
“过滤器能实现的多功能在Spring Security中页得到了体现”里面错别字 “页”应该为“也”
7 楼 三杠online 2014-12-17  
必须支持一下
6 楼 c.hle2008 2014-08-09  
找了这么久终于找到一本像样的书了,老师很强大,学习学习,java界需要您。
5 楼 tw_wangzhengquan 2014-01-26  
去西单的新华书店转了一圈也没发现关于这方面的书,那些关于Spring的书也就是介绍了几个AOP之类的等等,初学者看看还行。后来在网上搜了一下,发现廖雪峰的《Spring.2.0核心技术与最佳实践》写的不错也靠谱,可惜是基于spring2.0的,有些过时。今天终于发现了您的博客,久旱逢甘霖啊
4 楼 tw_wangzhengquan 2014-01-26  
中国需要像您一样的人
3 楼 loweryou 2012-12-19  
这一篇足足看了两个小时,并且还不怎么熟悉,还得深入!
2 楼 grosso 2012-11-20  
为什么ss3要用抛异常来check是不是有用户,而不是一个方法。
1 楼 consy 2012-10-24  
翻译的很好,受益匪浅

相关推荐

    《Spring Security3》第二章第三部分翻译(下)附前两章doc文档

    《Spring Security3》第二章第三部分的翻译下篇主要涵盖了Spring Security的核心概念和技术,这部分内容是深入理解Spring Security架构和实现安全控制的关键。在本章节中,我们将详细探讨以下几个核心知识点: 1. *...

    springSecurity3中文文档

    第二章:springsecurity起步 第三章:增强用户体验 第四章:凭证安全存储 第五章:精确的访问控制 第六章:高级配置和扩展 第七章:访问控制列表(ACL) 第八章:对OpenID开放 第九章:LDAP目录服务 第十章:使用...

    Spring Security3

    #### 第二章:Spring Security起步 **安全的核心概念** - **认证**:验证用户身份的过程。 - **授权**:根据认证结果决定用户可以执行的操作。 **实现步骤** 1. **配置Spring Security的XML文件**: - 定义了安全...

    Spring Security3 中文版 张卫滨 推荐

    ### 第二章:Spring Security起步 这一章重点介绍了如何快速集成Spring Security到现有的项目中。 - **安全的核心概念**:深入浅出地解释了安全领域的重要概念,如认证、授权等。 - **实现Spring Security的XML...

    spring security3中文文档

    #### 第二章:Spring Security起步 - **安全的核心概念**:深入探讨认证与授权等核心概念。 - **认证**:详细介绍认证的过程及其实现方式。 - **授权**:讲解授权的概念以及在Spring Security中的实现方式。 - **三...

    Spring Security权限管理开发手册

    - **第3章:自定义数据库表结构** - **自定义表结构:** 根据项目的具体需求,自定义数据库表结构以存储更加复杂的用户信息和权限数据。 - **初始化数据:** 在数据库中填充初始数据,以便后续的测试和验证。 - *...

    Pro+Spring+Security

    第二章:介绍Spring Security(Introducing Spring Security) - Spring Security概述:解释Spring Security框架的作用以及如何在Spring应用中集成安全功能。 - 基础配置:介绍如何设置Spring Security的基本配置,...

    SpringSecurity 中文

    #### 第二章:Spring Security 起步 **安全的核心概念** - **认证**:验证用户身份的过程。 - **授权**:根据用户的角色和权限决定其可以访问哪些资源。 **三步之内使我们的应用变得安全** 1. **配置Spring ...

    Spring攻略PDF版

     第3章 Spring中的Bean配置   3.1 在Spring IoC容器里配置Bean   3.1.1 问题描述   3.1.2 解决方案   3.1.3 实现方法   3.2 实例化Spring IoC容器   3.2.1 问题描述   3.2.2 解决方案...

    spring-security-oauth2文档

    #### 二、Spring Security OAuth2 Boot 2.6.8版本概述 Spring Security OAuth2 Boot 2.6.8作为最后一版的官方文档,提供了关于如何使用Spring Security OAuth2 Boot来简化授权和资源服务器设置的方法。这一版本支持...

    Spring攻略中文版PDF

     第3章 Spring中的Bean配置   3.1 在Spring IoC容器里配置Bean   3.1.1 问题描述   3.1.2 解决方案   3.1.3 实现方法   3.2 实例化Spring IoC容器   3.2.1 问题描述   3.2.2 解决方案...

    spring3核心包及第三方插件包

    Spring3 是一个强大的Java应用程序框架,它以IoC(Inversion of Control)和AOP(Aspect ...而"chapter2"可能包含的是书中的第二章内容,具体涉及了Spring框架的初步介绍和基本配置,是学习整个Spring3体系的基石。

    Spring攻略英文版(附带源码)

     第3章 Spring中的Bean配置   3.1 在Spring IoC容器里配置Bean   3.1.1 问题描述   3.1.2 解决方案   3.1.3 实现方法   3.2 实例化Spring IoC容器   3.2.1 问题描述   3.2.2 解决方案   ...

    springlive(共11章)

    2. **第二章:搭建Spring环境** - 安装与配置:介绍如何配置Java开发环境,包括JDK、IDE和构建工具如Maven或Gradle。 - 创建第一个Spring项目:逐步指导创建一个简单的Spring项目,体验Spring的基本配置。 3. **...

    spring in action 第二版 中文 3(共3个)

    在压缩包中包含的两个部分分别是“Spring+in+Action(第二版)中文版(381-450).pdf”和“Spring+in+Action(第二版)中文版(451-505).pdf”,这代表了书籍的两个章节段落。根据页码范围,我们可以推测这些章节涵盖了...

Global site tag (gtag.js) - Google Analytics