也晒晒我的RBAC系统(二):系统实现原理简介

     在阅读这篇文章以前,建议大家先看一下Wenzy发布的“Asp.net RBAC membership framework For Visual Studio 2005 免费开源的Asp.net 权限管理系统http://www.cnblogs.com/wenzy/articles/504124.html),本人的RBAC系统从中借鉴了很多非常好的思路,在此要向Wenzy兄表示感谢。具体的数据库建模图请看本系列的第一篇,这里不再重复给出。

 

要实现权限验证,首先必须有对具体权限的定义。在没有RBAC的情况下,一些简单的系统是把权限定义直接写死,整个系统有几种角色都提前定义好,在使用中只能给用户分配固定的角色。编程时,哪个模块需要做权限验证,就在哪个模块中直接编写代码,根据用户所属角色来设定用户在模块中具有的权限。这样的方法实现起来最简单,但也是最不灵活的,因为每个涉及到权限控制的部分都需要编写相应的判定代码。如果新增一个新的角色,那所有涉及到权限验证的模块都需要增加对新角色的验证代码,非常不灵活。

合适的方法是在项目编程前和编程过程中,定义出来系统中共有多少模块,每个模块涉及到有什么权限,最后汇总出一个总的权限列表来。在使用中可以由用户自己定义角色及角色权限。这样在编程时,判断当前用户是否有权调用某项权限时,只要判断一下用户所属角色是否具有此权限即可。可以通过一个通用的验证模块来完成权限验证工作,也简化了编程工作。如下图这个示例,首先定义出了所有权限并存储于数据库中,然后定义角色、角色具有的各项权限、角色所属用户,也存储到数据库中。这样在使用中涉及到某项权限,如使用“客户查询”时,通过验证模块就能判断出当前用户是否有权使用,如果有则进入,没有则退出。此种方法的缺点是系统规模较大或权限设定较细的情况下,需要定义的权限非常多,会大大增加编程工作量。

 

说了这么多后,该说一下本系统的实现原理了。首先还是权限的定义,但此处权限不是直接定义的,而是通过“资源-操作”组合对来定义。

首先需要定义出系统中涉及到的所有资源(ksRBAC_Resources表和ksRBAC_ResourceGroups表)。如库存管理中的仓库、车辆,销售系统中的商品、柜组等。每一项内容都可以定义成一项资源,且可以无限细分。在这里,还引入了资源组的概念,通过资源组及下属资源组的划分,使不同资源能够进行分类归档,方便了资源的管理。

其次需要定义操作(ksRBAC_Operations表),操作是指允许对某项资源进行何种操作行为。如针对仓库的操作有出库、入库、盘点等,针对车辆的操作有驾驶、保养,针对商品的操作有添加、删除、销售、进货、退货等等。

有了资源与操作,就能够定义权限了(ksRBAC_Privilgegs表)。所谓的权限,其实就是定义了可以对某项资源进行何种操作,即“资源-操作”组合对。如商品销售是一个权限定义,驾驶汽车也是一个权限定义。具体需要定义那些权限,是根据项目的实际需要来设置的。如资产管理的项目,会定义驾驶汽车、保养汽车、报废汽车的权限来跟踪车辆生命周期过程,而办公管理的项目,则只会定义驾驶汽车一项权限,因为其只关心汽车的使用而不关心保养问题。

 

定义完了权限,就该定义角色了(ksRBAC_Roles表)。本系统中关于角色的定义比较简单,因为考虑到一个系统中的角色不会有很多,所以角色部分没有设置分组功能。

 

 

至此,系统权限的基本架构已经完成,通过上面的各个数据表,已经能够很好存储项目中所定义的各项权限、角色和授权了。

 

定义好角色权限后,有两种权限验证方式。一种是将用户加入某个角色,在进行权限(Privilege)验证时,首先得到用户所属角色,然后对此角色进行权限(Privilege)验证。采用此种方法,由于验证对象是角色,因此用户只能加入一个角色,使用上不是很灵活,

本系统采用了另一种方法,将权限验证对象降低为具体用户。一个用户,可以同时加入多个角色。在用户登录时,首先得到用户所属的角色列表,然后依次得到授权(Permission)给每个角色的权限(Privilege)集合,最后将每一项权限(Privilege)加入用户的权限列表中。这样在使用时,只要判断用户的权限列表中是否具有指定的权限(Privilege)即可完成验证工作。

对于用户的定义,此处涉及到了三个表。ksRBAC_User是基础表,负责存储用户的登陆名称和密码等最基础的信息。ksRBAC_UserMembership表为权限表,用于存储与权限验证有关的内容。ksRBAC_UserDetail表是用户基本信息表,用于存储用户的各种资料信息。基本信息表在项目中由用户自己根据实际需求定义字段内容,保证在不同项目用户资料不一致的情况下,此表能够灵活适应各种情况。

 

 

前面说了权限的存储与验证机制,那么在具体编程过程中,如何确定一个权限。也就是说,程序怎么知道这个模块的这个操作表示权限A,那个模块的那个操作就表示权限B呢?这里需要通过硬编码来完成。

例如用户在使用商品模块,需要执行入库操作时,首先程序会拿出代表“入库操作”这一权限的ID号,然后用此ID和用户的权限列表进行比对,判断其中是否存在此ID,如果有则继续向下执行,没有的话则提示用户权限不足并不再继续。至于权限的ID号,可以从数据库中查询得出,在编码时直接写出来即可。

如果在编程时仅仅做到上面这一步,那么虽然可以实现系统所需的全部功能,但是在编程中指定权限时,还需要知道权限的ID号,非常不方便。因此实际操作中是提前定义了一个权限文件,在其中使用以权限名称命名的字符传来存储权限ID号,在使用时直接输入权限名称,就能得到权限ID了。

 

说了这么多,系统的实现原理就介绍的基本差不多了。有些地方说得不是很细,会在以后的文章中展开介绍的。欢迎大家共同探讨。

posted @ 2008-09-17 10:27  行一山人  阅读(5005)  评论(9编辑  收藏  举报