基于角色的权限管理(RBAC)
——我一直不太信任自己的记忆力,所以我把它们都写下来
这几天一直想把web项目中菜单的管理梳理一遍,今天终于写了个小Demo。在这个过程中融合了linux权限管理的思想。具体的阐述记录在代码中,我相信这个注释将会非常详细。
需要说明的是这个Demo只是单纯的一种思想,是不能直接用于商业开发的。这个demo对菜单的数量很敏感,不能太多。菜单多一个,存储都是以指数级增加的。
项目结构如下图:
Main.java中是菜单权限控制的核心
package com.albert.test;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.albert.model.Menu;
import com.albert.model.Person;
import com.albert.model.Role;
import com.albert.service.BaseService;
/**
* @{#} Main.java Created on 2015-11-19 上午11:57:18
* 主测试方法
*/
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
BaseService service = new BaseService();
List<Role> roles = service.initRole();
List<Menu> menus = service.initMenu();
/**
* 模拟当前登录用户,目前写死为张三,ID是1
*/
Person curPerson = service.initPerson().get(0);
/**
* 当前登录用户的角色
*/
Role curRole = null;
for(Role r : roles){
if(curPerson.getRoleId()==r.getId()){
curRole = r;
break;
}
}
System.out.println("当前用户:"+ curPerson.getName());
System.out.println("当前角色:"+ curRole.getName());
/**
* 当前用户的menu
*/
List<Menu> curMenus = new ArrayList<Menu>();
/**
* 当前用户menu的父menu
*/
Set<Menu> parentMenus = new HashSet<Menu>();
/**
* 这个for语句块是这个demo的核心加重点。
* t_menu表中所有子菜单都有一个不重复的sn,比如《用户新增》的sn是0,
* 《用户修改》的sn是1;
*
* 某个角色(t_role)对以上两个菜单有权限,那么acl = 2^0+2^1,
* 也就是3。看到这里是不是一头雾水?
*
* 验证这个角色是否有《用户修改》权限,只需要 &运算符,即 2^1 & 3,
* 结果是2,非0即说明拥有该权限。
*
* 这个原理如下:
* 3 二进制 0000 0011
* 2 二进制 0000 0010
* &运算后 0000 0010 非0,则有这个权限
*/
for(Menu m : menus){
Double sn = Math.pow(2d, m.getSn());
if((sn.intValue() & curRole.getAcl())!=0){
curMenus.add(m);
for(Menu n : menus){
if(m.getPid() == n.getId()){
parentMenus.add(n);
}
}
}
}
//显示菜单(打印到控制台)
for(Menu m : parentMenus){
System.out.println("》"+m.getName());
for(Menu n : curMenus){
if(n.getPid() == m.getId()){
System.out.println(" |"+n.getName());
}
}
}
}
}
运行main方法打印控制台输出如下
项目svn地址:http://code.taobao.org/svn/TestRbac/TestRbac