AGILEJ的权限控制
随着互联网络的发展,信息资源的共享越来越频繁,访问控制也就显得尤为重要。防止对任何资源进行未授权的访问,从而使软件系统在合法范围内使用;决定用户能做什么,也决定代表一定用户利益的软件系统该做什么。
在AgileJava的项目中我们将会采用RBAC的访问控制原型,RBAC全称为Role-Based Access Control,即基于角色的访问控制。RBAC中,许可(permission)和角色相关,用户作为某角色的成员而获得该角色的许可。RBAC的主要目的是为了便利管理。RBAC的核心是许可(permission)关联角色,不同用户将会被赋予不同的角色。角色和许可以及用户和角色之间都是多对多的关系。举个例子,用户A可能是HR经理同时又是公司的VP,这样用户A对应了两个角色;这两个角色可能各自拥有不同的permission:作为HR经理他可以看到公司内部所有员工的档案,而作为VP他可以看到公司业务部门起草的所有文件并予以省批。
在agilejava的项目中我们的模型包括一个用户表(user),角色表(role),许可(permission)和资源(resource),其中的关联关系如图1。
图1
与标准的rbac模型并没有太多区别。
其中注意的一点是角色所对应的表是基于树实现的,所以在ROLE表中每条记录将会有有一个左值(LEFT_VALUE)和一个右值(RIGHT_VALUE)属性,关于这其中涉及的算法问题将会在下一篇文中提及。
RBAC与传统访问控制的差别在于多了一个Role层,进而带来了灵活性。而在我们的权限控制中角色是可继承性的,及角色A拥有其下属角色所拥有的任何许可(permission),比如某公司的董事长将会拥有财务部经理的所有权限。
RBAC的优势:便于授权管理,访问的精度可以控制的很细,便于赋予用户最小特权;便于根据工作需要进行分级,如经销部门跟其他部门可以通过采购员这个角色予以区分;便于任务分组,不同角色完成不同的任务;便于资源分级,比如角色A和角色B都可以看到文档C,A可以执行修改动作,而B不可以。
agileJ的RBAC模块中主要的function:基本的增删改查操作,以及关联对象的分配和移除功能(如角色分配,许可分配)。功能方面的具体实现将会在后继文档中展现。
AGILEJ的权限控制(角色树的算法):
在权限控制的第一篇文中我们提到了在我们RBAC的模型中角色将是可继承性的,即如果角色A财务部经理是角色B财务员的父类,则角色A将会拥有角色B的所有权限,那么一个公司/组织的结构则是一个树型结构。在这里我们将会虚拟一个根节点,作为所有角色的祖先。如下图所示。
树的遍历通常有两种,第一种是按层次遍历,在图中的表示就是从根节点A开始,一层一层的向下走,每一个子节点按照它自己的parent节点来确定位置。通常使用这种遍历会保存节点的路径和该节点的父亲节点ID,对于图中K节点来说,它将会把路径ABCFK和F存储在自己的对象属性中。这种遍历的一个好处就是插入节点很方便,比如我要给K添加一个子节点,只需要查出K的路径,结合K对应的ID就可以了。但是如果是要求查询出一个节点(比如C)的所有子节点呢?很自然的想法是通过数据库的模糊查询找出路径属性包含C的所有记录,不过这样做就出现了一个性能问题,通过这种模糊查询方式速度会很慢。
第二种就是先根遍历,也是在AGILEJ的权限控制里面使用到的。具体的思想就是按照链状来构造树结构。如图所示,这颗树就是按照1-2-3...20-21-22的顺序来遍历的。对于每个节点我们为其添加了两个属性--左值和右值。现在如果我们要查询节点C的所有子节点,只需要找出数据表中所有左值大于C左值(3)并且右值小于C右值(10)的所有节点即可,这样就避免了使用模糊查询。如果我只是要查出C节点下面所有子节点的数目而非详细信息,那么可以用(C的右值-C的左值-1)/2,即(10-3-1)/2=3,是不是很方便?不过这种算法也有弱点,就是插比起层次遍历的方法要麻烦点。比如我要为H添加一个子节点,那我必须将所有左值大于12的节点的左值加上2,所有右值大于12的节点的右值加2,然后插入一条数据,其左值为14,右值为15.
简单实现(假设节点C对应的object为roleC):
查询节点c的所有子节点:
8y7mn5T-q _4Q_0collection = find all role where role.left_value>roleC.leftValue and role.right_value
B9l x-)T E0update role set role.rightValue=role.rightValue+2 where role.rightValue>=roleM.rightValueAgileJava Space{#r2J0T x'S
now save new Node with leftValue=roleM.leftValue+1 and rightValue=roleM.leftValue+2
?3_USH[ hf~0
对于权限控制的模型来说,需要进行节点添加删除的操作相对比较少,而查询使用的却会很多。因此先根遍历是一个不错的选择。
本来该系列的第二篇是打算写写rbac中的算法,但是前两天跟steay讨论了一个多小时,决定还是继续来解释下AgileJ里面的权限模型。
这里首先说下,目前的权限模型(RBAC)是hierachical和Composite类型的。在引子里面已经介绍了对角色的控制是基于树来执行的,在这里把hierachical和composite的概念放到树上来解释下,如图1是一个角色树
Hierarchical的意思是角色是可继承的。如果一个用户被分配了图1中的C角色,那他将会拥有C角色所有子角色的权限,即包含FGK的所有权限,注意的一点是FGK的权限总集将会不大于角色C的权限。
Composite的意思是角色是可符合性的。举个例子,用户可以在图中同时被分配了角色G和角色D,他拥有这两个角色对应的权限的合集。
几个问题的讨论。
关于区分部门和部门的员工。我们的rbac模型是基于角色的,因此在角色树中也就没有部门这个概念。对于一个部门来说,对应于角色树的一个子树(subtree),比如图中的C-F-K-G,假设该部门的老大被分配了角色C,那他将会拥有该部门内所有子角色拥有的一切权利;而有的时候,如果有其他需求,比如讨论时提到的部门经理有时候可能不能看到开发团队的代码之类,这种情况下,我们可以把给部门经理分配角色F,他拥有管理其下所有成员的权限,而G节点可能对应的是该部门查看代码权限的角色,具体是什么完全自由扩展。
关于工作流中的分配模型。工作流系统中上级部门会将任务分配给下级部门。因为我们的权限控制模型是基于角色的,所以不存在部门的概念,任务的分配只是看你当前的角色是否拥有向下分配任务的许可。在这里我们可以定义一个许可(下发任务),如果某角色定义了这个下发任务的许可,此角色对应的相关人员将会拥有对以此角色为根节点的子树分配任务的权限。还是看C-F-K-G这颗子树,如果我们给C分配了下发任务的许可,则其可以给拥有FGK节点角色的人分配任务,当然你完全可以限制C只给他的直接下属分配任务,那么这个子树就只进行一个level,即C-F-G。
没有评论:
发表评论