身份验证只是Spring Security安全机制的第一步,访问决策管理器验证用户是否有权限访问相应的资源(filterSecurityInterceptor中objectDefinitionSource属性定义的访问URL需要的属性信息)。
org.springframework.security.AccessDecisionManager接口定义了用于验证用户是否有权限访问受保护资源的decide方法,另一个supports方法根据受保护资源的配置属性(即访问这些资源所需的权限)来判断该访问决策管理器是否能做出针对该资源的访问决策。decide方法最终决定用户有无访问权限,如果没有则抛出AccessDeniedException异常(面前也提到过,你应该在回过头去看看)。
与认证管理器类似,访问决策管理器也不是由自己来实现访问控制的,而是通过一组投票者来投票决定(通过调用投票者的vote方法),访问决策管理器统计投票结果并最终完成决策工作。下表列出了系统提供的3个访问决策管理器的实现:
访问决策管理器 | 如 何 决 策 |
AffirmativeBased | 当至少有一个投票者投允许访问票时允许访问 |
ConsensusBased | 当所有投票者都投允许访问票时允许访问 |
UnanimousBased | 当没有投票者投拒绝访问票时允许访问 |
decisionVoters属性为访问决策管理器定义了一组进行投票工作的投票者,那么这些投票者是如何进行投票的呢?这就需要提 org.springframework.security.vote.AccessDecisionVoter接口,所有的投票者都实现了这个接口并实现了其中的vote方法。该接口中还定义了3个int类型的常量:
int ACCESS_GRANTED = 1;(投赞成票)
int ACCESS_ABSTAIN = 0;(投弃权票)
int ACCESS_DENIED = -1; (投反对票)
每个决策投票者都返回这3个常量中一个,这取决与用户是否有权限访问当前请求的资源,访问决策管理器再对这些投票结果进行统计。认证投票者的配置如上面所示。
loggerListener是一个可选项,它和我们前面配置的Bean或者过滤器没有关系,只是监听系统的一些事件(实现了 ApplicationListener监听接口),被它监听的事件包括AuthenticationCredentialsNotFoundEvent 事件,AuthorizationFailureEvent事件,AuthorizedEvent事件,PublicInvocationEvent事件,相信你从他们的名字就能看出来是一些什么样的事件,除非你的e文比我还差劲。loggerListener配置如下:
到此,本例所涉及到的所有配置都介绍完了,在下一篇中会介绍方法安全拦截器,以及如何使用它来保护我们的方法调用,以及前面提到过的会在下一篇中介绍的,这里不在一一列出。
接下来就是JSP页面了,首先是login.jsp:
2 登录失败,请重试。错误原因: < br />
3 < font color ="red" >
4 < c:if test ="${not empty SPRING_SECURITY_LAST_EXCEPTION}" >
5 < c:out value ="${SPRING_SECURITY_LAST_EXCEPTION}" ></ c:out >
6 </ c:if >
7 </ font >
8 </ c:if >
9 < form action ="<c:url value=" /j_spring_security_check" /> " method="post">
10 < table >
11 < tr >
12 < td >< label for ="username" > username: </ label ></ td >
13 < td >< input type ="text" id ="username" name ="j_username"
value="<c:out value="${SPRING_SECURITY_LAST_USERNAME}"/>"/></td>
14 </ tr >
15 < tr >
16 < td >< label for ="password" > password: </ label ></ td >
17 < td >< input type ="password" id ="password" name ="j_password" value ="" /></ td >
18 </ tr >
19 < tr >< td ></ td >
20 < td >< input type ="checkbox" name ="_spring_security_remember_me" > 两周内记住我 </ td >
21 </ tr >
22 < tr >< td colspan ="2" >< input type ="submit" value ="提交" />
23 < input type ="reset" value ="重置" /></ td ></ tr >
24 </ table >
25 </ form >
如果你有看源代码,上面的某些参数,以及本文所有提及的东西你都不应该感到陌生。其它页面也不在列出了,还有就是如何让它运行起来,这些我相信你都能自己搞定。
附件1:linux/springsecurity.rar">springsecurity.rar(不包括JAR包)
补上使用命名空间配置实现的代码,命名空间的详细资料请参考Spring Security中文参考文档,翻译得很好,这里就不在累述了,配置文件中也有比较详细的注释。另外例子中还包括了自定义 UserDetailService的实现已经如何Ehcache缓存用户信息,详细的信息将在下一篇中讲述。
附件2:linux/springsecurity-namespace.rar">springsecurity-namespace.rar(包括部分JAR包)