位运算实现ACL授权与认证过程的原理解析

来源:互联网 发布:openwrt 获取mac地址 编辑:程序博客网 时间:2024/04/20 18:06

在任何权限管理系统中,ACL(Access Control List)都是非常重要且有不可或缺的。权限管理主要包括授权与认证两大部分,下面就看ACL是如何实现授权与认证的。


先需要知道什么是授权与认证


关于授权比较详细的解释:


1、授权,指将权限授予角色或用户

   a)如果用户A拥有角色B、角色C,那么,缺省的情况下,用户A将拥有被分配给角色B和角色C的所有权限(即默认情况下,用户A继承其拥有的角色所具有的所有权限);

   b)如果用户拥有多个角色,那么用户的权限是这些角色权限的合集;

   c)如果用户拥有多个角色,而且角色之间的授权有冲突(比如对同一个资源的同一个操作,一个角色为“允许”,另外一个角色为“不允许”),将以优先级别高的角色(所谓优先级别,也就是对于这个用户所拥有的角色而言,是有顺序的,同一个角色在不同的用户那里可能拥有不同的优先级);

   d)除了可以对角色进行授权外,也可以针对用户进行授权,也就是说,将权限授予用户。针对某个资源的所有操作,我们可以设置这些权限对用户来说是“继承”或“不继承”;

       i.继承:意思是这些权限将使用其(即用户)所拥有的角色的权限,而不使用其(即用户)单独设置的权限,

       ii.不继承:意思是这些权限将使用其单独设置的权限,而不使用其所拥有的角色的权限。


一言以蔽之:授权就是颁发许可证的过程。比如导游证,你有了导游证,你就可以上岗;如果没有,对不起,你玩去。授权就相当于与授予你导游证的过程。


注意需要的说明一点:什么是角色?这里有了用户,为什么还要有角色,用户与角色有什么不同?

角色是抽象的概念。角色可以理解为职位,比如系统管理员,部门经理等这些职位,而用户就是具体的人。一个用户可以身兼多职,一个职务也可以有多个人来负责。所以人员与角色是多对多的关系。


关于认证比较详细的解释:


2、认证,指用户访问资源的某些操作时,根据授权,判断是否允许用户的访问

   a)在用户访问的时候,需要进行即时的判断(是否有权访问)

   b)应该提供查询的功能,可以查询某个用户所拥有的所有权限


一言以蔽之:认证是一个检查过程。给你颁发的导游证,上岗前还需要对你进行检查,如果检查出来你没有导游证,对不起,你不能上岗。


ACL在代码中的体现


知道了什么是授权与认证,下面看授权与认证如何在代码中体现。下面是一个访问控制类ACL的实现。

package com.lzq.model;/** * ACL类   访问控制类 */public class ACL {/** * 授权允许:  不确定   不允许   允许 */public static final int ACL_NEUTRAL = -1;public static final int ACL_NO = 0;public static final int ACL_YES = 1; /** * 授权状态,用其后四位(bit)来表示CRUD操作 */private int aclState;/** * 表示是否继承,0表示不继承,1表示继承 *  */private int aclTriState;public int getAclState() {return aclState;}public void setAclState(int aclState) {this.aclState = aclState;}public int getAclTriState() {return aclTriState;}public void setAclTriState(int aclTriState) {this.aclTriState = aclTriState;}/** * acl实例跟主体和资源关联 * 针对此实例进行授权,某种操作是否允许 * @param permission 只可取0、1、2、3 * @param yes true表示允许,false表示不允许 */public void setPermission(int permission,boolean yes){int temp = 1;temp =temp <<permission;if (yes) {aclState |= temp;}else {aclState &= ~temp;}}/** * 获得ACL授权 * @param permission C/R/U/D授权 * @return 授权标识,允许/不允许/不确定 */public int getPermission(int permission){//如果继承,则返回未定的授权信息if (aclTriState == 0xFFFFFFFF) {return ACL_NEUTRAL;}int temp = 1;temp = temp << permission;temp &=aclState;if (temp !=0) {return ACL_YES;}return ACL_NO;}/** * 设置本授权是否是继承的 * @param yes true表示继承,false表示不继承 */public void setExtends(boolean yes){//0xFFFFFFFF是-1的补码表示if (yes) {aclTriState =0xFFFFFFFF;}else {aclTriState = 0;}}public static void main(String[] args) {System.out.println(0xFFFFFFFF);}}


位运算如何实现授权与认证


假设从右向左, 分别代表CRUD。那么, 我们CRUD的代码就应该是0123(也就是移位时要移的位数), 因为我们要进行移位进行认证。


1、授权与取消授权部分:


拿D操作来举例说明:

一个int temp =1的临时变量,aclState为原始授权状态。temp的二进制代码表示是:00000000 00000000 00000000 00000001;

D对应的代码是3。根据temp = temp<<permission,将temp向左移3位。temp变为:00000000 00000000 00000000 00001000;

假设原始授权是aclState=00000000 00000000 00000000 00000101;

当变量yes=true时,为授权。将temp与aclState求|运算,因为temp现在只有他要授权的位为1,求或运算后,aclState=00000000 00000000 00000000 00001101。这样就授权成功。

当变量yes=false时,为取消授权。将temp取反为:~temp=11111111 11111111 11111111 11110111。然后与aclState原状态做与运算。运算后,aclState= 00000000 00000000 00000000 00000101,仍未原状态,授权取消。


一言以蔽之:授权的过程,就是经过位运算,将移动后的位(R移动1位,移动后对应的位为从右到左第二位;U移动2位,移动后对应的位为从右到左第三位)变为1;取消授权就是经过位运算后,原状态未发生变化。


代码实现如下:

/** * 针对此实例进行授权,某种操作是否允许 * @param permission 只可取0、1、2、3 * @param yes true表示允许,false表示不允许 */public void setPermission(int permission,boolean yes){int temp = 1;temp =temp <<permission;if (yes) {aclState |= temp;}else {aclState &= ~temp;}}



2、认证部分:


认证的过程与授权的过程可以认为是逆过程。

认证中仍然拿D操作来举例:首先看继承状态,如果继承状态aclTriState=-1 (0xFFFFFFFF为-1的补码表示)表明授权状态未确定;

一个int temp =1的临时变量,aclState为原始授权状态。temp的二进制表示为:00000000 00000000 00000000 00000001;

D对应的代码是3。根据temp = temp<<permission,将temp向左移3位。temp变为:00000000 00000000 00000000 00001000;

假设原始的授权状态aclState=aclState=00000000 00000000 00000000 00001101;

临时变量temp与aclState做与运算。temp=temp&aclState=00000000 00000000 00000000 00001000,这时temp不等于0,表示获取ACL授权。


一言以蔽之:认证实现就是授权的逆过程,将授权状态与移动后的temp做与运算,如果结果不等于0,表示获取ACL授权;如果结果等于零,表示不能获取授权(与授权过程相对应)。


代码实现如下:

/** * 获得ACL授权 * @param permission C/R/U/D授权 * @return 授权标识,允许/不允许/不确定 */public int getPermission(int permission){//如果继承,则返回未定的授权信息if (aclTriState == 0xFFFFFFFF) {return ACL_NEUTRAL;}int temp = 1;temp = temp << permission;temp &=aclState;if (temp !=0) {return ACL_YES;}return ACL_NO;}



3、设置本授权是否是继承的


权限不仅能够授予给角色,也能够直接授权给用户。直接授权给用户的时候,要进行是否继承判断。

继承意思是这些权限将使用用户所拥有的角色的权限,而不使用用户单独设置的权限;

不继承:意思是这些权限将使用其单独设置的权限,而不使用其所拥有的角色的权限。

如果yes为true,那么aclTriState=-1,表示本授权是继承的;如果yes为false,那么aclTriState=0,表示本授权是不继承的。

代码实现如下:


/** * 设置本授权是否是继承的 * @param yes true表示继承,false表示不继承 */public void setExtends(boolean yes){//0xFFFFFFFF是-1的补码表示if (yes) {aclTriState =0xFFFFFFFF;}else {aclTriState = 0;}}

位运算简介


基本的位操作符有与、或、异或、取反、左移、右移这6种,它们的运算规则如下所示:

 

符号

 描述

 运算规则        

&      

 

两个位都为1时,结果才为1

|  

     

两个位都为0时,结果才为0

^    

异或

两个位相同为0,相异为1

~   

取反

0110

<< 

左移

各二进位全部左移若干位,高位丢弃,低位补0

>> 

右移

各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)

注意以下几点:

1.在这6种操作符,只有~取反是单目操作符,其它5种都是双目操作符。

2.位操作只能用于整形数据,对float和double类型进行位操作会被编译器报错。


总结


本文主要介绍了授权与认证的概念,位运算基础的简单介绍,如何通过位运算进行授权与认证。大家可以对照最后给出的位运算表格,对授权和认证过程进行比对,看它们具体是如何实现的。

其实一条acl授权记录中除了aclState和aclTriState之外,还主要记录了:角色、资源和授权三条信息。具体内容在后文介绍。