《Spring Security3》第二章第三部分翻译(中)(转载)

请求是怎样被授权的?

Spring Security 的默认过滤器链中,最后一个 servelt 过滤器是 FilterSecurityInterceptor ,它的作用是判断一个特定的请求是被允许还是被拒绝。在 FilterSecurityInterceptor 被触发的时候,安全实体已经经过了认证,所以系统知道他们是合法的用户。(其实也有可能是匿名的用户,译者注)。请记住的一点是, Authentication 提供了一个方法( (List<GrantedAuthority>

getAuthorities() ),将会返回当前安全实体的一系列权限列表。授权的过程将使用这个方法提供的信息来决定一个特定的请求是否会被允许。

 

需要记住的是授权是一个二进制的决策——一个用户要么有要么没有访问一个受保护资源的权限。在授权中,没有模棱两可的情景。

Spring Security 中,良好的面向对象设计随处可见,在授权决策管理中也不例外。回忆一下我们在本章前面的讨论,一个名为访问控制决策器( access decision manager )的组件负责作出授权决策。

Spring Security 中, o.s.s.access.AccessDecisionManager 接口定义了两个简单而合理的方法,它们能够用于请求的决策判断流程:

<!--[if !supportLists]-->l  <!--[endif]-->supports :这个逻辑操作实际上包含两个方法,它们允许 AccessDecisionManager 的实现类判断是否支持当前的请求。

<!--[if !supportLists]-->l  <!--[endif]-->decide :基于请求的上下文和安全配置,允许 AccessDecisionManager 去核实访问是否被允许以及请求是否能够被接受。 decide 方法实际上没有返回值,通过抛出异常来表明对请求访问的拒绝。

 

AuthenticationException 及其子类在认证过程中的使用很类似,特定类型的异常能够表明应用在授权决策中的不同处理结果。 o.s.s.access.AccessDeniedException 是在授权领域里最常见的异常,因此值得过滤器链进行特殊的处理。我们将在第六章中详细介绍它的高级配置。

AccessDecisionManager 是能够通过标准的 Spring bean 绑定和引用实现完全的自定义配置。 AccessDecisionManager 的默认实现提供了一个基于 AccessDecisionVoter 接口和投票集合的授权机制。

投票器( voter )是在授权过程中的一个重要角色,它的作用是评估以下的内容:

<!--[if !supportLists]-->l  <!--[endif]-->要访问受保护资源的请求所对应上下文(如 URL 请求的 IP 地址);

<!--[if !supportLists]-->l  <!--[endif]-->用户的凭证信息(如果存在的话);

<!--[if !supportLists]-->l  <!--[endif]-->要试图访问的受保护资源;

<!--[if !supportLists]-->l  <!--[endif]-->系统的配置以及要访问资源本身的配置参数。

AccessDecisionManager 还会负责传递要请求资源的访问声明信息(在代码中为 ConfigAttribute 接口的实现类)给投票器。在 web URL 的请求中,投票器将会得到资源的访问声明信息。如果看一下我们配置文件中非常基础的拦截声明,我们能够看到 ROLE_USER 被设置为访问配置并用于用户试图访问的资源:

 

<intercept-url pattern="/*" access="ROLE_USER"/>

投票器将会对用户是否能够访问指定的资源做出一个判断。 Spring Security 允许过滤器在三种决策结果中做出一种选择,它们的逻辑定义在 o.s.s.access.AccessDecisionVoter 接口中通过常量进行了定义。

决策类型

描述

Grant (ACCESS_GRANTED)

投票器允许对资源的访问

Deny (ACCESS_DENIED)

投票器拒绝对资源的访问

Abstain (ACCESS_ABSTAIN)

投票器对是否能够访问做了弃权处理(即没有做出决定)。可能在多种原因下发生,如:

<!--[if !supportLists]-->l  <!--[endif]-->投票器没有确凿的判断信息;

<!--[if !supportLists]-->l  <!--[endif]-->投票器不能对这种类型的请求做出决策。

正如你从访问决策相关类和接口的设计中可以猜到的那样, Spring Security 的这部分被精心设计,所以认证和访问控制的使用场景并不仅仅限于 web 领域。我们将会在:精确的访问控制 中关于方法级别的安全时,再次讲解投票器和访问控制管理。

当将他们组合在一起,“对 web 请求的默认认证检查”的整体流程将如下图所示:



 我们可以看到 ConfigAttribute 能够从配置声明(在 DefaultFilterInvocationSecurityMetadataSource 类中保存)中传递数据到投票器,投票器并不需要其他的类来理解 ConfigAttribute 的内容。这种分离能够为新类型的安全声明(例如我们将要看到的方法安全声明)使用相同的访问决策模式提供基础。

配置 access decision 集合

实际上 Spring Security 允许通过 security 命名空间来配置 AccessDecisionManager <http> 元素的 access-decision-manager-ref 属性来指明一个实现了 AccessDecisionManager Spring Bean Spring Security 提供了这个接口的三个实现类,都在 o.s.s.access.vote 包中:

类名

描述

AffirmativeBased

如果有任何一个投票器允许访问,请求将被立刻允许,而不管之前可能有的拒绝决定。

ConsensusBased

多数票(允许或拒绝)决定了 AccessDecisionManager 的结果。平局的投票和空票(全是弃权的)的结果是可配置的。

UnanimousBased

所有的投票器必须全是允许的,否则访问将被拒绝。

 

配置使用 UnanimousBased 的访问决策管理器( access decision manager

如果你想修改我们的应用来使用 UnanimousBased 访问决策管理器,我们需要修改两个地方。首先让我们在 <http> 元素上添加 access-decision-manager-ref 属性:

 

<http auto-config="true"

      access-decision-manager-ref="unanimousBased" >

这是一个标准的 Spring Bean 的引用,所以这需要对应一个 bean id 属性。接下来,我们要定义这个 bean (在 dogstore-base.xml 中),并与我们引用的有相同的 id

 

<bean class="org.springframework.security.access.vote.UnanimousBased"

      id="unanimousBased">

  <property name="decisionVoters">

    <list>

      <ref bean="roleVoter"/>

      <ref bean="authenticatedVoter"/>

    </list>

  </property>

</bean>

<bean class="org.springframework.security.access.vote.RoleVoter"

id="roleVoter"/>

<bean class="org.springframework.security.access.vote.

AuthenticatedVoter" id="authenticatedVoter"/>

你可能象知道 decisionVoters 属性是什么。这个属性在我们不声明 AccessDecisionManager 时,是自动配置的。默认的 AccessDecisionManager 要求我们配置投票器的一个列表,它们将会在认证决策时用到。这里列出的两个投票器是 security 命名空间配置默认提供的。

遗憾的是, Spring Security 没有为我们提供太多的投票器,但是实现 AccessDecisionVoter 接口并在配置中添加我们的实现并不是一件困难的事情。我们将在第六章看一个例子。

我们引用的两个投票器介绍如下:

类名

描述

例子

o.s.s.access.

vote.RoleVoter

检查用户是否拥有声明角色的权限( GrantedAuthority )。 access 属性定义了 GrantedAuthority 的一个列表。预期会有 ROLE_ 前缀,但这也是可配置的。

access="ROLE_USER,ROLE_ADMIN"

o.s.s.access.

vote.AuthenticatedVoter

支持特定类型的声明,允许使用通配符:

<!--[if !supportLists]-->l  <!--[endif]-->IS_AUTHENTICATED_FULLY ——允许提供完整的用户名和密码的用户访问;

<!--[if !supportLists]-->l  <!--[endif]-->IS_AUTHENTICATED_REMEMBERED ——如果用户是通过 remember me 功能认证的则允许访问;

<!--[if !supportLists]-->l  <!--[endif]-->IS_AUTHENTICATED_ANONYMOUSLY ——允许匿名用户访问。

access=" IS_AUTHENTICATED_ANONYMOUSLY"

猜你喜欢

转载自kongcodecenter.iteye.com/blog/1320021