二、权限系统的设计
权限往往是一个极其复杂的问题,
设计权限系统第一个要解决的问题就是什么样的行为是需要权限控制,什么样的是业务方法。他们之间本来是没有明确的区分,任何权限从某种角度上说可以是一种业务方法。为了以后管理和开发方面我们从概念上需要将权限和业务明确划分清楚,指导开发。
权限控制行为
: 对What(Which)进行How的操作需要区分
Who
,具有
Who
身份差异性和可替换性。
我们将此类操作作为权限。
特点:可以收回也可以分配的,具有一定的抽象级别。
消耗资源,行为结果具备一些持久性的影响。
业务逻辑行为
: 对What(Which)进行How的操作的时候与Who的身份无关或者具有
Who
身份差异性但 是不具有可替换性。
特点:不能抽象和共享,很难回收和分配。不消耗资源,不产生持久性。现实中也存在某一时期行为是业务逻辑,最后演变成权限控制,或者相反的过程。
1、粗粒度权限设计
采用
自主型访问控制方法,操作给予访问控制列表。
每一个用户通过角色获得一组权限集合,权限系统的功能是验证用户申请的权限(集合)是否在这个集合当中,即申请的权限(集合)是否投影在用户拥有的权限集合
,
换句话说:
只要某用户直接或者间接的属于某个Role那么它就具备这个Role的所有权限许可。
一个
自主型访问控制方法的权限系统包括以下几个部分:角色、权限、访问控制表、
l
权限
描述一个权限可以通过以下几个要素说明:
类型(
class
)
:
名称(
name
):
动作
(actions)
:
掩码(
mask
):
属性:
具体权限
Example:
1
、
Test
类型(
class
)
:com.yangjs.secutiry. permissions. TestPermission
名称(
name
):如:
test.*
,
test.sub.* ,test.sub1.sub2
动作
(actions)
:
brower_detail ,post,repost,……
掩码(
mask
):
0x1,0x2,0x4…..
属性:
无
l
存取控制器(
my--acl.xml
)配置
存取控制项(
ACE
)
:角色到权限的映射集合,表示某个角色可以在某些资源上执行某些动作
,
它们之间通过
role
关联(继承),
ACE
之间产生包含关系。
存取控制列表(
ACL
):
ACE
的集合。
我们的存取控制器(
ACL
)是通过一个
xml
的配置文件说明,存取控制列表由多个存取控制项(
ACE
)来描述。
使用方法
(略)
2、细粒度权限设计
细粒度授权需要上下文的支持,而且每个权限控制的上下问题都不一样,这由相关的业务逻辑决定,而且此类授权一般变化较快,应此需要将强的可维护性和扩展性,支持变化,但又不能够太复杂,否则缺乏可执行性。虽然此类权限个性化较强,我们仍然可以总结出很多共性:
1.
几乎所有的授权需要用户的角色和ID.
2.
特定的上下文几乎都同用户资源使用情况相关.
我们将此类信息称为UserState 即:User角色以及资源使用情况和当前状态。大部分信息我们在用户登陆的时候已经。获得。授权贯穿Web层和Biz层,因此我们的登陆要独立于Web端。因此上下文我们可以用UserState结合其他来抽象。
关于上下文的维护问题,我们不可能将UserState此类参数在Web层和Biz层来回传递,更加不能在需要授权的地方都加上一个这样的方法参数,这样不太现实。其次如果在授权的地方再从数据库中取一次这样虽然能够解决部分问题(不能解决userId的传递),这样效率太低,不能接受。
解决方法就是将此类信息
cache
起来,用的时候再去取,由于此类信息具有非常高的并发性,对线程安全较高,因此我们决定将此类信息放入一个线程上下文的内存
cache
中。此外我们由于引入
cache
,就需要解决所有
cache
共有的维护性问题。
Cache
的生命周期:用户的一次请求,属于线程级,用户请求线程结束,
Cache
结束。
Cache
的更新:当上下文信息发生变化是需要及时更新
Cache
,这是一个不可避免的步骤。
Cache
丢失:发生在如系统
down
机,线程崩溃,内存溢出等等,对用户来说就是当前请求突然中断。
当用户重新发送请求,我们的系统就需要重新验证用户,此时我们可以更新
Cache
解
决丢失问题。
Cache
的清理:这个实现就是当用户请求结束,返回应答的时候清理,可以通过
Filter
实现,比较简单。
以上是相关的原理部分,我们看看系统地实现:
实现:
线程上下文的
cache
实现类: