如题,希望和大家探讨一下基于角色的用户权限设计的问题
我的初步想法如下:
MSSQL的库
设计表:
Users  用户表 字段:userid,username,userpermission
Roles  角色表 字段:roleid,rolename,rolepermission
UserInRole 用户角色对应表 字段:userid,roleid
PermissionList 权限列表 字段:permissionid,permissionDescription,permissionGroup权限设计:许可、禁止和未设置三种状态,Allow,Deny,Not Set目标:
实现用户权限的定义。
首先定义角色权限,用户与角色间是多对多的关系。用户权限继承自角色权限。
情况一:用户所属的多个角色存在权限冲突时,取最小权限,即某权限角色A许可,角色B禁止,则该权限为禁止。
情况二:用户所属的角色均未对某权限进行设置时,即NotSet状态,则该权限同DENY
情况三:用户所属的角色对某权限为许可时,也可单独设置该权限为禁止。功能:
设置用户权限:
 默认情况下,用户权限继承自所属角色的权限
 可单独设置某用户的权限
扩展权限
 权限定义可随时增加,并可以分组。当增加权限时,默认的角色权限均为未设置状态问题:
1、在MSSQL数据库中如何设置userpermission和rolepermission字段的字段类型?
2、如何存取用户权限?特别是当用户属于多个角色时,如何高效的设置用户权限的问题先就问这么多的,还有些问题,等想清楚了再问,或是和大家探讨的时候,想起来了再问吧!

解决方案 »

  1.   

    对于可单独设置某用户的权限这种情况,你完全可以将这个用户作为一个私有的角色去处理(即Roles表中有个该用户名的角色,该角色只属于这个用户所拥有),这样,你就不必区分是不是用户还是角色,统一都以角色来处理权限问题。数据表的设计,PermissionList 这个表应该只是定义有哪几种权限,所以应该还有另一张表,存放Permission和Roles的关系的表,比如叫PermissionSetting,其中字段为PermissionId,RoleId.
    所以,userpermission,rolepermission这些字段是不需要的。获取用户权权限,就根据用户和角色的关联,然后在PermissionSetting查找就可以了,不难的。
      

  2.   

    我的思路是这样的,以一个用户管理系统为例
    permissionlist中数据如下:
    permissionid,permissionDescription,permissionGroup
    1, AddUser , 用户管理组
    2, DelUser , 用户管理组
    3, EditUser , 用户管理组
    4, AddRole , 角色管理
    5, DelRole , 角色管理
    6, EditRole , 角色管理
    7, AddMember , 角色管理
    8, RemoveMember , 角色管理角色中定义一个账号管理员的角色.这个角色专门用来添加/删除用户的
    则其权限为1,2,3许可,其他未设置
    另一个角色管理员,权限为4,5,6,7,8为许可,其他未设置.

    若用户A同时属于两个角色时,则拥有全部权限
    我原来的想法是设置userpermission为binary字段,存取长的二进制数.权限可按位取.
    如账号管理员的角色权限值为11100000,
      角色管理员的角色权限值为00011111,
    则用户A的权限为两个角色的按位进行或运算的值为11111111.
    但编程实现起来好像很不方便.
    而且存成binary字段的话,要将长串0101的字符做为二进制数存进SQL数据库,好像实现起来也不那么容易.因为要将0101的字符串转为int型,大点也就是bigint型,受其大小限制,01字符串的长度不可能超过30位.也就是权限定义不超过30个.所以不知道怎么搞了.
    再则,当用户所属的角色过多时,或运算量就可能会比较大,可能会影响程序性能.当然,用户权限在继承自角色权限时,就只运行一次或运算,之后将其权限值存入userpermission中,这样或许会加强一点点性能.因此,就上述问题,希望大家再提供点宝贵意见
      

  3.   

    你的设计是有缺点。用户的权限时实的保存在数据库是不可取的。并且,用户的权限是通过角色来获取的,userpermission这个字段是没有意义的。
    另外,permissionGroup和角色是什么关系?
    感觉乱乱的。不知是你没看我上面的回复还是你没有明白我上面的回复的意思
      

  4.   

    MyLf(不睡觉的鱼) , 首先非常感谢你参与我提出的问题的讨论并给出很好的建议。你认为的userpermission字段没意义,我是这样认为的,用户属于多个角色时,程序每次去取多个角色权限并进行相关的运算,从性能上来讲是不可取的,我认为只用一次设置好用户权限,以后每次只取这一个userpermission就OK了。permissiongroup和角色并没有任何联系。只是便于取一组权限。不用一次取整个权限字段。假设当有一百个权限时,我可能只用取A组中的五个权限就够。因为只需要判断用户在某模块范围内的相关权限,没必要取所有权限看过你先前的回复,你想的和我想的可能完全不一样。你可能没有理解我设的rolepermission的用意。或许看过我上面的回复应该清楚点吧。也可能是我没明白你的意思。
    如果按你的思路,那是不是要每个用户都要单独设置权限呢?
    顺便再提一下我之前的设计吧。
    之前我还要两个表,分别是userpermission和rolepermission即用户权限和角色权限表。字段为用户ID(角色ID),权限ID,权限值(ALLOW,DENY,NOTSET)
    这样的话,每个用户(角色)的每一个权限就是一条记录。觉得没必要。可以直接用一个userpermission或rolepermission字段表示,所以就取消了这两个表。分别在users 和roles表中加了permission这个字段。这个字段中就存010101010这样的长字符串。位数对应权限表中的ID号,相应位数上的0和1表示禁止或许可。
    不知道我的这套方案是否可行。
    一点点个人拙见,还望继续探讨
      

  5.   

    情况一:用户所属的多个角色存在权限冲突时,取最小权限,即某权限角色A许可,角色B禁止,则该权限为禁止。若用户A同时属于两个角色时,则拥有全部权限这两句话有矛盾。楼主的主要思想不明确!
    我只知道你弄个权限管理!
      

  6.   

    serversql(啊初) ,哪有矛盾啊?再说了,存在矛盾是必然的~  ^_^
    举个例子吧,
    ROLEA的权限列表为   0001110111001
    ROLEB的权限列表为   0001110111002
    USERA的权限列表为   0001110111002
    上述两个角色的权限就存在冲突,
    当用户同时属于角色A和B时,用户最后一位的权限为禁止(0表示未设置,1表示许可,2表示禁止)
    我第二个回复中举的例子是这样的
    ROLEA的权限列表为   1110000
    ROLEB的权限列表为   0001111
    USERB的权限列表为   1111111
    当用户同时属于上述两个角色时,则拥有全部权限这里要说明一点:先前可能一直忘了提[未设置]这个权限。所以楼上的说我这有矛盾。
    我的问题似乎越来越清晰了。
    欢迎大家继续讨论
      

  7.   

    找到一个类似的问题,可能和不睡觉的鱼的想法差不多http://forum.javaeye.com/viewtopic.php?t=15953&sid=7cc2af0d4ba7bc79461d5bf4d4a96e7f
    参考一下吧
      

  8.   

    是不是要每个用户都要单独设置权限呢?
    ------用户的权限是取决于角色的,当然不会对用户去设单独的权限。更简单的说,设权限是对角色来说的,跟用户没关系,只是用户属于了某些角色,那他就拥有了相关的权限。你的用户权限和角色权限是分开的(userpermission,rolepermission)??如果userpermission的值勤是根据rolepermission的值计算出来,那么我给你指出你的方案的问题:
    1.rolepermission字段你将定义为什么类型?多长?如果目前只有3类权限,RoleA的权限可能是"010",如果增加了一类权限,可能就是"0110",那你的数据要如何处理?2.删除了RoleA,或是修改了RoleA的权限设置,你就得去更新属于RoleA的所有用户的userpermission. 你成功的修改了吗?
    RoleA:012
    RoleB:101
    RoleC:102
    如果UserA同时属于这三个角色,那么userpermission为112,我没说错吧?
    现在,将RoleA改为011,你怎么样去处理,然后得到userpermission仍为112? 是不是先将所有属于RoleA的用户取出来,在处理其中某一用户的时候,将该用户的所属角色的rolepermission都取出来,然后再和RoleA的rolepermission去比较,然后得到该用户的userpermission仍为112?
    如果是把RoleA删除了
    我前面已经说了,用户的权限时实的保存在数据库是不可取的,至少我是不会这么做的。也许,我们理解的方向就不一样,可能我没理解你的方案吧。 仅供建议
      

  9.   

    咦写了这么多字,就被占了两楼了。Ivony() 说的意思和我一样的,就是权限只是基本于角色的。
    至于要为用户设单独的权限,那就是用户有自己的私有角色。
    发觉我的废话很多。第一次回复我就说清楚了:
    “对于可单独设置某用户的权限这种情况,你完全可以将这个用户作为一个私有的角色去处理(即Roles表中有个该用户名的角色,该角色只属于这个用户所拥有),这样,你就不必区分是不是用户还是角色,统一都以角色来处理权限问题”
      

  10.   

    Ivony() ,MyLf(不睡觉的鱼) 我想我明白你们的意思了.的确是不错的.
    或许基于角色的用户权限设置的最终目标是统一都以角色来处理权限问题
    只是我想,如果每个用户单独创建一个私有的角色的话,那我就是要在ROLES表中加一个Private字段,以表示该角色是私有的?那新加的角色权限实际上就等同于我原来设置的userpermission.这样说对吗?
      

  11.   

    是的,至于加不加字段标识其实只是显示的问题,在显示角色列表的时候把这些私有角色给屏蔽掉,提供优秀的用户界面。你也可以通过特殊的命名等来解决。至于权限的储存,如果权限多且可能变化的话,不建议用二进制储存。如果权限相对固定,并且数量少,则可以考虑二进制储存。
    储存的时候应该使用两位二进制保存一个权限,因为是三值逻辑。遵循这样的原则:
    未设置:00
    Allow: 01
    Deny:  11计算的时候,先将所有角色的权限按位或。
    然后再将相邻的两位异或即可算出权限。
      

  12.   

    00 | 01 = 01 XOR = 1
    00 | 11 = 11 XOR = 0
    01 | 11 = 11 XOR = 0
    00 | 11 = 11 XOR = 0
    00 | 00 = 00 XOR = 0
    00 | 01 | 11 = 11 XOR = 0
      

  13.   

    看来我是要结贴了,非常感谢各位的帮助。不过还有另一种权限,以后再开贴问各位吧。
    先提一下,上述的是基于角色的用户权限设置。还有一种,也是最近又想到的另一种权限设置,是基于对像的,或称之为资源吧。
    具体问题还没想清楚,以后再提吧~!
    特别感谢:MyLf(不睡觉的鱼) 、Ivony() 、立冬(立冬的想法一直没提,希望有时间回复一下啦)