权限算法 2的权的和

系统权限判定   

有时,系统需要做权限时,在数据库中,我们可能会简单设计“用户”表、“操作项”表及“用户操作项分录”表,需要检查某个操作权限时,只需在“用户操作项分录”表中查询即可。

下面介绍另两种简单的算法,可以不需要中间表“用户操作项分录”。
两种简单权限算法(一)
两种简单权限算法(二)
1:先来看一组数字:
	2^2+2^4+2^5=52
	52 &(2^2)=52 & 4= 4 =2^2
	52 & (2^5)=52 &32= 32 =2^5
	52 & (2^3)=52 &8= 0 !=2^3
	52 & (2^1)=52 &2= 0 != 2^1
	注:此处“^”为次方,不是异或。
从数字中可以发现,52是2^2、2^4、2^5的“和”,而有趣的是,拿这个“和”(即52)分别与2^2、2^4或2^5做“逻辑与”运算时,得到的值还是2^2、2^4或2^5。而52与其它数做逻辑与运算时,得到的值则不会与其相等。
正是这种现象(数学不好,不知道这种现象叫什么),我们可以把“操作项”表中的每个操作项都添加一个数字编码,如:
	操作A-->1
	操作B-->2
	操作C-->3
	操作B-->4
	操作B-->5
假设某个用户包含:操作A和操作C的权限,则可以在用户实体中记录他的权限为2^1+2^3=10,其中1和3是操作项对应的编码。当需要检查此用户是否包含某此权限时,则可以直接用逻辑与运算,而不需再查数据库中的中间表。
如:检查是否包含操作X(对应的编码为N)的权限
  1. int v= 2^N;
  2. If( 10 & v ==v){
  3. return true;
  4. } else{
  5. return false;
  6. }
那么,为什么会样呢?
其实关键点在逻辑与的算法上,根据几个基本公式:
	0 & A=0
	1 & A=A
	A & A=A
可以得到,任意值A,&A后,结果还是A。
上面例子中的10,二进制为1010。1010就是2^1+2^3之和,没有出现进位,事实上,如果没有出同两个(或以上)的次方之和(底为2),则不可能出现进位,因为2的N次方的值永远都是1后面N个0。事实上2的N次方,只上左移N位而已。
那么:
	10 & 2^1=10 & 2-->1010 & 0010 =0010
		1010
	&	0010
	--------------
		0010
	10 & 2^4=10^16-->1010&10000=0 != 10000 !-->2^4
		01010
	&	10000
	----------------
		00000
所以,只是数字游戏而已。
最后补充下:
1:这种算法最大的优势是判断权限的速度快,底层只是位移,另一方面也可以多个权限一起验证,如 10 & (2^1+2^3)= 2^1+2^3,10 & (2^1+2^2) != 2^1+2^2。
2:上面提到一个前提条件:“如果没有出同两个(或以上)的次方之和(底为2)”,即同一个权限编码值,不能添加两次。当然,这只有在代码层面有bug才会出现。
3:操作项数量有限:java中,int占4字节,32位,只有32个操作项,long的话,才64个操作项。当然,可以用将权限分模块,每个模块分配几十上操作项是够用的。或用byte[],则可以不限数量了。

JAVA例子:
  1. public static void main(String[] args) {
  2. int x[]={ 1, 2, 3, 4, 5, 6, 7}; //权限id
  3. //总的权限,即有3和6的权限(2^3+2^6)
  4. int cx=( int)Math.pow( 2, 3)+( int)Math.pow( 2, 6);
  5. int c=( int)Math.pow( 2, 6); //要检查的权限
  6. int v = cx & c; //结果(cx & 2^?)
  7. System.out.println(c==v); //如果相同,则有此权限
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值