权限管理之基于ACL的实现:讲解授权、认证、获得用户权限过程

权限管理模块的实现,需要多个用例:管理模块信息、管理用户信息、管理角色信息、给用户分配角色、给角色授权、给用户授权、获取用户授权列表、判断用户对某个模块的某操作是否允许授权

其中比较重要的是:授权、认证、获得用户拥有的所有授权。下面一一介绍:

 

授权过程

就是把系统现有模块授权给用户或角色

 

授权与取消授权的实现代码:

public void setPermission(int permission,boolean yes){  
        int temp = 1;  
        temp = temp << permission;  
        if(yes){  
            aclState |= temp;  
        }else{  
            aclState &= ~temp;  
        }  
    }  

 

比如,setPermission(2,true)表示授予 update 权限。

一个int temp = 1的临时变量, aclState为原始授权状态

tmp的二进制表示是: 00000000 00000000 0000000000000001 

将tmp左移2位得到updatetemp = tmp < < 2; temp变成:00000000 00000000 00000000 00000100 ,而第三位代表的就是Update权限。所以也能得出,左移0123就能得到CreateDeleteUpdateSelect权限。

 

假设原始授权aclState=00000000 00000000 0000000000001010 

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

当变量yes=false时,为取消授权,先将temp取反,即为1111111111111111 11111111 11111011,现在只有要取消权限的位为0,其余全为1,然后与aclState求&运算,则除了要取消权限的位变0,其余的都不变,即aclState=0000000000000000 00000000 00001010

 

授权过程



/**
 * 授权
 * @param principalType主体类型
 * @param principalSn 主体标识
 * @param resourceSn 资源标识
 * @param permission权限:C/R/U/D
 * @param yes是否允许,true表示允许;false表示不允许
 */
public void addOrUpdatePermission(String principalType, intprincipalSn,
int resourceSn, int permission, boolean yes) {
 
//根据主体标识和资源标识查找ACL实例
ACL acl = findACL(principalType, principalSn, resourceSn);
 
//如果存在ACL实例,则更新其授权
if(acl != null){
acl.setPermission(permission, yes);
getHibernateTemplate().update(acl);
return;
}
 
//不存在ACL实例,则创建ACL实例
acl = new ACL();
acl.setPrincipalType(principalType);
acl.setPrincipalSn(principalSn);
acl.setResourceSn(resourceSn);
acl.setPermission(permission, yes);
getHibernateTemplate().save(acl);
}

认证过程

判断用户对某个模块的某操作是否是允许的


认证的实现代码:

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; 
}  

如果继承,则返回未定的授权信息,需要进一步根据角色判断。

否则,直接将temp变量与aclState求&,temp为1的位为要验证的权限,其余全为0,如果aclState对应的这一位为1,则结果不为零,即有该操作权限;若aclState这一位为0,则结果为0,即没有该操作权限

 

认证过程


/**
 * 即时认证
 * 判断用户对某模块的某操作的授权(允许或不允许)
 * @param userId 用户标识
 * @param reourceSn 资源标识
 * @param permission 权限(C/R/U/D)
 * @return 允许(true)或不允许(false)
 */
publicboolean hasPermission(int userId, int resourceSn, int permission) {
 
//查找直接授予用户的授权
ACLacl = findACL(ACL.TYPE_USER, userId, resourceSn);
 
if(acl!= null){
intyesOrNo = acl.getPermission(permission);
 
//如果是确定的授权
if(yesOrNo!= ACL.ACL_NEUTRAL){
returnyesOrNo == ACL.ACL_YES ? true : false;
}
}
 
//继续查找用户的角色授权(优先级别由高到低)
Stringhql = "select r.id from UsersRoles ur join ur.role r join ur.user u "+
"whereu.id = ? order by ur.orderNo asc";
ListaclIds = getHibernateTemplate().find(hql, userId);
 
//依照角色优先级依次查找其授权
for(Iterator iter = aclIds.iterator(); iter.hasNext();) {
Integerrid = (Integer) iter.next();
acl= findACL(ACL.TYPE_ROLE, rid, resourceSn);
 
//一旦发现授权,即可返回结果
if(acl!= null){
returnacl.getPermission(permission) == ACL.ACL_YES ? true : false;
}
}
 
returnfalse;
}


获得用户拥有的所有授权过程

在用户登陆系统之后,需要根据用户的被授权情况,允许用户对这些模块进行操作。

要获得用户拥有的所有授权,可以分四个步骤进行

1、查找授予用户拥有的角色的所有权限列表(按优先级从低到高查找)

2、查找直接授予用户的权限列表(所有不继承的权限)

3、将这些授权依次合并。在合并过程中,优先级高的授权将覆盖优先级低的授权;直接授予用户的授权将覆盖继承而来的授权,从而达到不继承的目的。

4、至此,可以得到用户的授权列表,删除那些没有读取权限的授权,即可得到最终的列表

 

/**
 * 搜索某个用户拥有读取权限的模块列表(用于登录,形成导航菜单的时候)
 * @param userId 用户标识
 * @return 模块列表(即列表的元素是Module对象)
 */
publicList searchModules(int userId) {
 
//定义临时变量
Maptemp = new HashMap();
 
//按优先级从低到高查找用户拥有的角色
Stringhql = "select r.id from UsersRoles ur join ur.role r join ur.user u "+
"whereu.id = ? order by ur.orderNo desc";
ListaclIds = getHibernateTemplate().find(hql, userId);
 
//依次循环角色,合并权限,优先级高的授权将覆盖优先级低的授权
for(Iterator iter = aclIds.iterator(); iter.hasNext();) {
Integerrid = (Integer) iter.next();
 
//根据角色获得角色拥有的授权列表
Listacls = findRoleACLs(rid);
 
//把授权放入临时变量
for(Iterator iterator = acls.iterator(); iterator.hasNext();) {
ACLacl = (ACL) iterator.next();
//因为角色是按优先级从低到高遍历的,所以对于同一资源,优先级低的会被优先级高的覆盖
temp.put(acl.getResourceSn(),acl);        
}
}
 
//查找直接授予用户的授权列表
Listacls = findUserACLs(userId);
for(Iterator iter = acls.iterator(); iter.hasNext();) {
ACLacl = (ACL) iter.next();
//同样,对于同一资源,会覆盖掉继承而来的权限,从而达到不继承的目的
temp.put(acl.getResourceSn(),acl);        
}
 
//现在已获得用户拥有的所有授权(包括直接授予用户的以及用户继承角色的授权)
//遍历所有权限,如果没有读取权限,则在临时变量中删除这个授权
 
//遍历授权列表,如果没有读取权限,则临时存放在list中记录下来(map结构在遍历时进行remove操作会影响结果)
ListdelResources = new ArrayList();
Setentries = temp.entrySet();
for(Iterator iter = entries.iterator(); iter.hasNext();) {
Map.Entryentry = (Map.Entry) iter.next();
ACLacl = (ACL)entry.getValue();
 
if(acl.getPermission(Permission.READ)== ACL.ACL_NO){
delResources.add(entry.getKey());
}
}
 
//在临时变量中删除这些需要删除的授权
for(Iterator iter = delResources.iterator(); iter.hasNext();) {
Objectkey = (Object) iter.next();
temp.remove(key);
}
 
//如果授权列表是空的,则返回0长度的集合
if(temp.isEmpty()){
returnnew ArrayList();
}
 
//现在已获得用户拥有读取权限的授权
StringsearchModules = "select m from Module m where m.id in (:ids)";
returngetSession().createQuery(searchModules)
.setParameterList("ids",temp.keySet())
.list();
}

这是授权、认证、获得用户权限过程的实现过程,也是权限管理最主要最复杂的地方 ,请关注下篇文章
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值