spring-security(二十五)鉴权

前言
本文将详细探讨spring security中的鉴权操作,包括AbstractSecurityInterceptor的不同实现,后面章节还会讨论更加精确的域对象访问控制。
1.架构
1.1 组件之Authorities
在[url=http://fengyilin.iteye.com/admin/blogs/2411035]核心组件[/url]章节,我们知道认证后的Authentication中都会存储一个GrantedAuthority列表,代表着当前认证用户所具有的权限信息。在鉴权阶段AccessDecisionManager从Authentication中读取到这个列表,并据此作出是否允许用户操作执行的判断。GrantedAuthority是一个接口,里面只有一个方法

String getAuthority();

通过这个方法,AccessDecisionManager能获取一个明确的代表权限信息的字符串,如果某个GrantedAuthority不能单纯的通过一个字符串来代表权限信息,这个GrantedAuthority应该被认为是一个“复合”权限,对应的getAuthority()方法必须返回null。
spring security为我们提供了一个GrantedAuthority的具体实现类:SimpleGrantedAuthority,这个类可以把用户设定的字符串转换成GrantedAuthority,spring security提供的各种AuthenticationProvider都是用SimpleGrantedAuthority这个类来组装Authentication的。
1.2 组件之AccessDecisionManager
spring security是通过拦截器来控制安全访问的,一个请求最终能否被执行是通过AccessDecisionManager类的decide来判断的。这个类是被AbstractSecurityInterceptor调用的,AccessDecisionManager接口包含下面三个方法

void decide(Authentication authentication, Object secureObject, Collection<ConfigAttribute> attrs) throws AccessDeniedException;
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);

AccessDecisionManager的decide方法会传入所有做出决定所需的信息。通常情况下,通过传入的安全对象,我们就可以获取到大部分所需的参数信息,例如:假定传入的对象是MethodInvocation,可以很容易的通过MethodInvocation获取任意的自定义参数,然后通过AccessDecisionManager中的判断逻辑来确保当前用户是可以针对这些参数执行操作的,如果不允许,应该抛出AccessDeniedException异常。
在应用启动时AbstractSecurityInterceptor会调用AccessDecisionManager的supports(ConfigAttribute)方法来检查当前的ConfigAttribute是否能被对应的Interceptor支持,如FilterSecurityInterceptor支持FilterInvocationSecurityMetadataSource对应的ConfigAttribute,MethodSecurityInterceptor支持MethodSecurityMetadataSource对应的ConfigAttribute。
supports(Class)用来判断当前Interceptor是否支持对应的Security object对象。
1.3 基于投票机制的AccessDecisionManager实现
尽管用户可以实现自己的AccessDecisionManager来控制鉴权的所有处理,为了方便,spring security也提供了几种基于投票机制的AccessDecisionManager实现,相关类关系如下:

[img]http://dl2.iteye.com/upload/attachment/0129/3056/d05d4868-3fe4-3b4d-95a1-5548403a75e6.png[/img]

从上图可以看出,AccessDecisionManager就是利用各种各样的AccessDecisionVoter的投票结果来做最后的决定的。AccessDecisionVoter接口的内容如下

int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attrs);
boolean supports(ConfigAttribute attribute);
boolean supports(Class clazz);

具体的AccessDecisionVoter实现者vote方法返回一个int值,对应的具体值在AccessDecisionVoter中定义成了常量:ACCESS_ABSTAIN, ACCESS_DENIED , ACCESS_GRANTED,分别代表弃权、拒绝、同意。
具体的AccessDecisionManager实现类有三个
[list]
[*]ConsensusBased 统计所有的投票结果,如果赞成大于反对旧赞成,如果发对大于赞成就抛异常,如果赞成和反对一样多,就看配置的allowIfEqualGrantedDeniedDecisions属性值,true的话就赞成,false就抛异常。
[*]AffirmativeBased(默认)只要有赞成的投票就赞成,如果所有的投票结果都没有赞成,并且有反对的票就抛出异常,否则就是所有的投票结果都是弃权,也是看看配置的allowIfEqualGrantedDeniedDecisions属性值,true的话就赞成,false就抛异常
[*]UnanimousBased 只要有反对的票就抛出异常,如果没有反对票并且有赞成票,也认为是赞成,否则就是所有的投票结果都是弃权,也是看看配置的allowIfEqualGrantedDeniedDecisions属性值,true的话就赞成,false就抛异常
[/list]
我们也可以通过自定义实现AccessDecisionManager,例如可以对各种投票的结果追加权重计算等。
1.4 组件之RoleVoter
实际应用中最常用AccessDecisionVoter的具体实现类是RoleVoter,以及有继承功能的RoleHierarchyVoter,这两个实现都是把配置属性单纯的当作角色名称,当用户有对应的角色权限时就投赞成票。
具体逻辑如下:
[list]
[*]当一个安全对象对应的ConfigAttribute以ROLE_开头,则进行投票,否则就弃权
[*]获取当前认证对象authentication中的权限列表,权限列表里面有和ConfigAttribute.getAttribute()返回值相同的权限时就赞成,否则投拒绝票
[/list]
1.5 组件之AuthenticatedVoter
不同于RoleVoter,这个实现类会根据当前的认证类型进行投票,主要用来区分匿名认证、remember-me认证、fully-authenticated认证。这种鉴权方式主要用在那种对remember-me认证有特殊访问限制的系统中
1.6 调用完后处理(After Invocation Handling)
AccessDecisionManager是AbstractSecurityInterceptor在执行安全对象之前进行调用的,没有权限抛出异常,从而用户限制调用。实际应用中,有的系统可能会希望在调用完成后再对返回结果进行修改,当然,借助spring aop,我们自己也能实现相应的逻辑,spring security给我们提供了更加便捷和ACL进行继承的默认实现,相关联的类如下:

[img]http://dl2.iteye.com/upload/attachment/0129/3058/64370e20-2e72-37a7-b681-08e7e226b1db.png[/img]

核心类是AfterInvocationManager,在调用完安全对象(FilterInvocation)后,会调用这个类的decide方法,具体的实现类是AfterInvocationProviderManager,里面有一个AfterInvocationProvider列表,每一个AfterInvocationProvider要么修改一下的结果,要么抛出异常。
1.7 继承角色
具体例子参考[url=http://fengyilin.iteye.com/admin/blogs/2410997]java config-sample之rolehierarchy[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值