在Spring Security的默认过滤器链中,最后一个servelt过滤器是FilterSecurityInterceptor,它的做用是判断一个特定的请求是被容许仍是被拒绝。在FilterSecurityInterceptor被触发的时候,安全实体已经通过了认证,因此系统知道他们是合法的用户。(其实也有多是匿名的用户,译者注)。请记住的一点是,Authentication提供了一个方法((List<GrantedAuthority> web
getAuthorities()),将会返回当前安全实体的一系列权限列表。受权的过程将使用这个方法提供的信息来决定一个特定的请求是否会被容许。spring
须要记住的是受权是一个二进制的决策——一个用户要么有要么没有访问一个受保护资源的权限。在受权中,没有模棱两可的情景。安全
在Spring Security中,良好的面向对象设计随处可见,在受权决策管理中也不例外。回忆一下咱们在本章前面的讨论,一个名为访问控制决策器(access decision manager)的组件负责做出受权决策。ide
在Spring Security中,o.s.s.access.AccessDecisionManager接口定义了两个简单而合理的方法,它们可以用于请求的决策判断流程:url
<!--[if !supportLists]-->l <!--[endif]-->supports:这个逻辑操做实际上包含两个方法,它们容许AccessDecisionManager的实现类判断是否支持当前的请求。spa
<!--[if !supportLists]-->l <!--[endif]-->decide:基于请求的上下文和安全配置,容许AccessDecisionManager去核实访问是否被容许以及请求是否可以被接受。decide方法实际上没有返回值,经过抛出异常来代表对请求访问的拒绝。设计
与AuthenticationException及其子类在认证过程当中的使用很相似,特定类型的异常可以代表应用在受权决策中的不一样处理结果。o.s.s.access.AccessDeniedException是在受权领域里最多见的异常,所以值得过滤器链进行特殊的处理。咱们将在第六章中详细介绍它的高级配置。xml
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的内容。这种分离可以为新类型的安全声明(例如咱们将要看到的方法安全声明)使用相同的访问决策模式提供基础。
实际上Spring Security容许经过security命名空间来配置AccessDecisionManager。<http>元素的access-decision-manager-ref属性来指明一个实现了AccessDecisionManager的Spring Bean。Spring Security提供了这个接口的三个实现类,都在o.s.s.access.vote包中:
类名 |
描述 |
AffirmativeBased |
若是有任何一个投票器容许访问,请求将被马上容许,而无论以前可能有的拒绝决定。 |
ConsensusBased |
多数票(容许或拒绝)决定了AccessDecisionManager的结果。平局的投票和空票(全是弃权的)的结果是可配置的。 |
UnanimousBased |
全部的投票器必须全是容许的,不然访问将被拒绝。 |
若是你想修改咱们的应用来使用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 |