二进制位运算实现权限系统

来源:互联网 发布:东方财富下载软件 编辑:程序博客网 时间:2024/05/06 18:49

1.传统用户权限存储方式
1>用户:rights:{“/hello.do”,“/hi.do”…}。
2>用户:rights:{1,2,3..}。
3>用户端不存储,每次去数据库查询比对。
弊端:1>当权限链接成百上千的时候,用户的权限链接存储浪费一定的内存资源,而且,每次比对效率较低。
2>若每次比对查询数据库,给数据库造成一定的压力影响程序的整体性能。

2.二进制位运算权限控制
优点:1>用户只需要存储权限总和long 或 long[](存储量极少)
2>权限比对的时候只需要用权限码与用户的权限总和进行位运算即可(比对效率极高)

实现原理及过程
过程:
1>权限表里面添加权限码字段rcode(java端Long 类型 mysql端 bigint类型)
rcode的计算方式:从1开始 每次递增为 上一位的权限码向左移动一位
(即 上一位权限码乘以2)
2>用户的权限总和
将用户所关联的权限集合中的每一条权限的权限码按照“或运算 |”的计算的
果即为用户的权限的总和。
3>权限比对
将要访问的链接的权限的权限码与用户的权限总和进行“与运算”若结果不为0
即表明用户有该权限。
原理:
若有权限码 1 0001
2 0010
4 0100
8 1000
若用户有1,2,8三条权限,则用户的权限总和
0001 | 0010 | 1000 =1011=11
此时若操作权限码为2(0010)的权限
权限总和 1011
& 0010
0010 > 0 (有操作权限)
此时若操作权限码为4(0100)的权限
权限总和 1011
& 0100
0000 = 0 (没有操作权限)
通过上面的例子不难发现:每一项权限(权限码) 对应一个二进制位,权限总和则表示用户拥有的所有权限(权限码)的二进制位。在进行比对的时候,某一个权限对应的权限码与权限总和进行“与运算”,即可说明用户是否有该权限。

致命的缺点:从上面的情况不难看出,数据库和Java程序中有符号的长整型最大为 2^63-1 加上原来的1 最多只可能有63(62+1)条权限。但这在实际的应用中63条权限显然是不够的。解决的办法:          1>给权限表添加一项权限组字段(rpos)          2>该字段从0开始,当权限码数量即将要满的时候,该字段加一          3>这样就可以有 n*63(63这里是最大值可以适当缩小)          4>用户权限总和采用long[]数组进行存储,每一权限组对应数组的下标。            例如:            public boolean hasRight(Rights r) {      return (rigths[r.getRpos()] & r.getRcode()) != 0;        }

到这里可能还会有其他疑问?
当一个用户请求到服务器是后,怎么获取权限组(rpos)和权限码(rcode)
呢?是不是也要根据action去数据库查询呢?
这里个人觉得将所有权限缓存在Nosql(redis)数据库中,每次需要比对的时候去Nosql数据库中查询,这样一来,减少mysql(主服务器)的压力,二来Nosql数据库检索的速度是非常高效的。当然你们有更好的办法也希望你们给我分享
mail:everyingo@ibeyond.me

0 0
原创粉丝点击