您的位置:首页 > 其它

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

2015-03-26 16:29 555 查看


ACL权限管理位运算

目录(?)[+]

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

关于授权比较详细的解释
关于认证比较详细的解释

ACL在代码中的体现

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

授权与取消授权部分
认证部分
设置本授权是否是继承的

位运算简介
总结

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

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

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

1、授权,指将权限授予角色或用户
a)如果用户A拥有角色B、角色C,那么,缺省的情况下,用户A将拥有被分配给角色B和角色C的所有权限(即默认情况下,用户A继承其拥有的角色所具有的所有权限);
b)如果用户拥有多个角色,那么用户的权限是这些角色权限的合集;
c)如果用户拥有多个角色,而且角色之间的授权有冲突(比如对同一个资源的同一个操作,一个角色为“允许”,另外一个角色为“不允许”),将以优先级别高的角色(所谓优先级别,也就是对于这个用户所拥有的角色而言,是有顺序的,同一个角色在不同的用户那里可能拥有不同的优先级);
d)除了可以对角色进行授权外,也可以针对用户进行授权,也就是说,将权限授予用户。针对某个资源的所有操作,我们可以设置这些权限对用户来说是“继承”或“不继承”;
i.继承:意思是这些权限将使用其(即用户)所拥有的角色的权限,而不使用其(即用户)单独设置的权限,
ii.不继承:意思是这些权限将使用其单独设置的权限,而不使用其所拥有的角色的权限。

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

注意需要的说明一点:什么是角色?这里有了用户,为什么还要有角色,用户与角色有什么不同?
角色是抽象的概念。角色可以理解为职位,比如系统管理员,部门经理等这些职位,而用户就是具体的人。一个用户可以身兼多职,一个职务也可以有多个人来负责。所以人员与角色是多对多的关系。

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

2、认证,指用户访问资源的某些操作时,根据授权,判断是否允许用户的访问
a)在用户访问的时候,需要进行即时的判断(是否有权访问)
b)应该提供查询的功能,可以查询某个用户所拥有的所有权限

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

ACL在代码中的体现

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

[java]
view plaincopyprint?

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); } }
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;取消授权就是经过位运算后,原状态未发生变化。

代码实现如下:

[java]
view plaincopyprint?

/** * 针对此实例进行授权,某种操作是否允许 * @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; } }

/**
* 针对此实例进行授权,某种操作是否允许
* @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授权;如果结果等于零,表示不能获取授权(与授权过程相对应)。

代码实现如下:

[java]
view plaincopyprint?

/** * 获得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; }

/**
* 获得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,表示本授权是不继承的。
代码实现如下:

[java]
view plaincopyprint?

/** * 设置本授权是否是继承的 * @param yes true表示继承,false表示不继承 */ public void setExtends(boolean yes){ //0xFFFFFFFF是-1的补码表示 if (yes) { aclTriState =0xFFFFFFFF; }else { 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
~
取反
0变1,1变0
<<
左移
各二进位全部左移若干位,高位丢弃,低位补0
>>
右移
各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)
注意以下几点:
1.在这6种操作符,只有~取反是单目操作符,其它5种都是双目操作符。
2.位操作只能用于整形数据,对float和double类型进行位操作会被编译器报错。

总结

本文主要介绍了授权与认证的概念,位运算基础的简单介绍,如何通过位运算进行授权与认证。大家可以对照最后给出的位运算表格,对授权和认证过程进行比对,看它们具体是如何实现的。
其实一条acl授权记录中除了aclState和aclTriState之外,还主要记录了:角色、资源和授权三条信息。具体内容在后文介绍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: