java权限系统设计_基于java的权限控制系统设计
⼀、概要
通常,需要单独的权限系统是解决授权的管理和维护,再分配等难题,不针对开发⽽⾔。
系统架构⽬标:在易于理解和管理,开发的前提下,满⾜绝⼤部分粗粒度和细粒度权限控制的功能需要。
除了粗粒度权限,系统中必然还会包括⽆数对具体Instance的细粒度权限。这些问题,被留给对框架的扩展⽅法来解决,这样的考虑基于以下两点:
1、细粒度的权限判断必须要在资源上获取权限分配的⽀持的上下⽂信息才可能得以实现。
2、细粒度的权限常常具有相当⼤的业务逻辑相关性。对不同的业务逻辑,常常意味着完全不同的权限判定原则和策略。相⽐之下,粗粒度的权限更具通⽤性,将其实现为⼀个架构,更有重⽤价值;⽽将细粒度的权限判断实现为⼀个架构级别的东西就显得繁琐,增加架构的复杂性。⽽且不是那么的有必要,⽤定制的代码来实现就更简洁,更灵活。否则会变成各种逻辑代码的堆砌。
⽐如,product post数量的控制,这种⼀般要知道⽤户个性化的信息,付钱数量到数据库中查最⾼数量,还要知道此⽤户已经有多少产品等,规则不具备通⽤性和重⽤性,
所以细粒度控制不应该放在权限架构层来解决。实例级的细粒度权限的解决⽅案就是将它转化为粗粒度权限,这样我们权限客户端就变得很简单了。
名词解释:
粗粒度权限 :⼀般可以通过配置⽂件来授权,授权只有真假,没有多少之分,不需要上下⽂的⽀持。
不消耗资源的。
逻辑表达式:判断“Who对What(Which)进⾏How的操作”的逻辑表达式是否为真。
别名:静态授权、类级授权
细粒度权限:不能通过配置⽂件等表达,需要特定上下⽂的⽀持.
逻辑表达式:判断“When(Where)的时候,Who对What(Which)进⾏How的操作”的逻辑表达式是否为真。
别名:动态授权、实例级授权
设计原则 :
框架只提供粗粒度的权限。
细粒度的权限也需要集中管理和维护
细粒度的权限通过定制的扩展代码将细粒度转化为粗粒度授权。
⼆、权限系统的设计
权限往往是⼀个极其复杂的问题, 设计权限系统第⼀个要解决的问题就是什么样的⾏为是需要权限控制,什么样的是业务⽅法。他们之间本来是没有明确的区分,任何权限从某种⾓度上说可以是⼀种业务⽅法。为了以后管理和开发⽅⾯我们从概念上需要将权限和业务明确划分清楚,指导开发。
权限控制⾏为: 对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 存取控制器(l)配置
存取控制项(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实现,⽐较简单。以上是相关的原理部分,我们看看系统地实现:
java上下文context实现:线程上下⽂的cache
实现类:com.yangjs.cache.ThreadContextCache:
public class ThreadContextCache {
public static Map asMap();
public static boolean containsKey(Object key);
public static boolean containsValue(Object key);
public static Object get(Object key);
public static void put(Object key, Object value);
public static Object remove(Object key);
public static void clean();
public static int size() ;
public static void destroy()
posted on 2007-04-16 09:17 EricWong 阅读(8573) 评论(7) 编辑 收藏 所属分类: Java
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论