博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

通用权限的设计(下)

Posted on 2009-06-07 11:01  linFen  阅读(525)  评论(1编辑  收藏  举报
我在通用权限的设计(上)一文中很多问题并没有诉说详细,而且估计我写“通用”两字的时候激发了很多人的不满,我这里先道个歉。

  从解决方案的角度出发,没有绝对通用的权限设计,这点我也赞同,只能针对项目的实际需求来开发对应的权限模块,这点是肯定的。我这里只是记录一种做法而已,而且这种做法必然有其适用的范围,而且如果把企业或者公司部门的因素也考虑进去,我觉得反而难以把做法说清,所以选择用最简单的设计来说明问题。实际情况下肯定要针对简单设计来做扩展的。

  上篇的图这里再插入一遍:

  通用权限的设计(下)

  我简单的说明一下,Application为功能模块表,他实际上没有什么具体作用,只是用来约束功能点的归属而已。Permission才是核心的功能点表,字段有最简单的功能名以及其他的字段,其中最重要的是功能点对应的权值(上篇说到的二进制编码),实际上这里没必要用0010这样的方式来保存,如果你的系统很小,功能点很少,那么可以用int类型来保存,权值只要满足2的n-1次方即可,至于原因是什么,我这里就没必要做说明了。那么以后业务扩充的功能点,只要满足这个权值规律就行了。如果系统的功能点再多点,可以考虑用bigint来保存,如果再大,可以考虑更大的类型来保存,甚至用字符来保存都可以,至于代码的接收,同样的需要有对应的类型来保存,小的不用说,大的可以参考http://pavelsem.blogspot.com/2008/04/big-number-calculations-in-c.html。针对这个功能表,我们可以做一个针对功能点的增删改操作,每次按照权值规律来赋值新的功能点,当然如果你比较懒,每次都在数据库里面加也可以,但是当数值较大的时候,每次估计都得拿个计算机来按了。所以大家大可估算一下这种做法的适用范围,以及当权值很大的时候,这种做法与传统做法哪中更好。

  讲完功能点,应该来讲一下如何创建角色,为什么角色与功能点之间完全没有关联,实际上很简单,我在上篇中已经把这个道理说明了,如果我们的功能点仍然有增加,删除,修改,查看,对应的权值分别是1,2,4,8,那么当我们创建一个角色B,要求角色B拥有这四个功能点的时候只需要进行如下操作:1 + 2 + 4 + 8 =15 即可,把15这个值以及新建的角色信息存入角色表即可。那么当用户登陆的时候,只需要从用户角色对应表当中找到对应的角色,并把角色的权值做计算即可,假如又有角色C的权值为1,而用户A同时具备角色B以及角色C,那么当用户登陆的时候只要根据关联表找到他对应的两个角色,再把角色B以及角色C的权值进行按位或操作,即:1 | 15 = 15,15这个值就是用户A所具有的权值了,我们把这个权值保存起来,放入Session或者Cookies当中,显然15这个权值与1,2,4,8做按位与操作的时候皆可得到1,2,4,8,于是用户A就得到了角色B以及角色C的权限,并且角色B跟角色C的权限已经进行了合并。至此,用户登陆完之后就与数据库脱离了关系,所有权限的判断只需要拿具体功能点的权值与用户的权值进行按位与操作即可,不用再查表或者遍历功能点集合。至于角色的更新,只需要把新计算出来的权值更新到对应的角色即可。

  针对实际情况,我们不可能在判断某个用户是否有某个功能点的时候都拿个数来与当前用户的权值做比较,更多是把它抽象为一个方法:

if (roleHandle.CheckUserPer("CreateTipType"))
{
  //..
}

  如上所示,CreateTipType对应的是一个业务的功能点名称,他对应一个权值,以上所说的过程全部集成在一个方法里面判断就可以了,当然你要用什么方式来做你的功能点与权值的对应都可以,并不一定要用名称,也可以用约定好的数字甚至其他表达方式都可以,但是绝对比你直接传个数字来得直观。

  采用这种做法的时候,还会碰到很多具体的问题,诸如菜单的生成,权值的配置,角色的配置,角色的更新,用户权值的更新与保存等实际问题,我这里就不做一一说明了,感兴趣的朋友我们可以一起讨论。