使用二进制 权限控制
分类: 项目模块2013-10-18 11:00 115人阅读 评论(0) 收藏 举报
二进制权限说明
权限由 int rightPostion(权限位/组) long rightCode(权限码) 组成
int[postion][code] :最大能到达 (2的31次方)*(63)
权限码Long:一个字节有8位,long有8个字节,一个long就有64位,一位代表一个权限,就能表示64个权限
有一位是符号位 所以一个long能代表63个权限.
权限位Int:Int有4个字节,32位,一位是符号位 最大为:2的31次方
我们只用63中的60个就好啦!
添加更新权限
[java] view plaincopy
/**
* 保存/更新权限
*/
public void saveOrUpdateRight(Right model){
//insert
if(model.getId() == null){
int rightPos = 0 ;
long rightCode = 1 ;
//查询最大权限位上的最大权限码
String hql = "select max(r.rightPos),max(r.rightCode) from Right r " +
"where r.rightPos = (select max(rr.rightPos) from Right rr)" ;
Object[] arr = (Object[]) this.uniqueResult(hql);
Integer topRightPos = (Integer) arr[0] ;
Long topRightCode = (Long) arr[1];
if(topRightPos == null){//如果表里还没有记录
rightPos = 0 ;
rightCode = 1 ;
}
else{
if(topRightCode >= (1L << 60)){
rightPos = topRightPos + 1;
rightCode = 1 ;
}
else{
rightPos = topRightPos ;
rightCode = topRightCode << 1 ;
}
}
model.setRightPos(rightPos);
model.setRightCode(rightCode);
}
this.saveOrUpdateEntity(model);
}
用户登入(得到具有的权限)
loginAction
[html] view plaincopy
/**
* 该方法只在doLogin之前运行
*/
public void validateDoLogin(){
User user =userService.validateLoginInfo(model.getEmail(),DataUtil.md5(model.getPassword()));
if(user == null){
addActionError("email/password wrong");
}
else{
//初始化权限总和数组
int maxRightPos = rightService.getMaxRightPos();
user.setRightSum(new long[maxRightPos + 1]);
//计算用户的权限总和
user.calculateRightSum();
//user--->session
sessionMap.put("user", user);
}
}
User Bean
[html] view plaincopy
//是否是超级管理员
private boolean superAdmin ;
//用户权限总和
private long[] rightSum ;
[html] view plaincopy
/**
* 计算用户的权限总和
*/
public void calculateRightSum() {
int pos = 0 ;
long code = 0 ;
for(Role role : roles){
//判断超级管理员
if("-1".equals(role.getRoleValue())){
this.superAdmin = true ;
roles = null ;//去除 User类里面与role的绑定 减小存放进Session的User的大小
return ;
}
for(Right r : role.getRights()){
pos = r.getRightPos() ;//权限位
code = r.getRightCode() ;//权限码
rightSum[pos] = rightSum[pos] | code ; //或运算叠加权限 (01101 | 10000= 11101)
}
}
roles = null ;
}
/**
* 判断用户是否有指定的权限
*/
public boolean hasRight(Right r) {
int pos = r.getRightPos();
long code = r.getRightCode();
long ret = rightSum[pos] & code ;
//权限总和与当前权限不等于0说明有权限(11101 & 00100=11101 有)
//权限总和与当前权限不等于0说明有权限(11101 & 00010=00000没 有)
return !(ret == 0);
}
RightFilterInterceptor
[html] view plaincopy
/**
* 判断是否有权限
*/
@SuppressWarnings("unchecked")
public static boolean hasRight(String ns,String actionName,HttpServletRequest req,BaseAction action){
if(!ValidateUtil.isValid(ns)
|| "/".equals(ns)){
ns = "" ;
}
//处理?参数
if(actionName.contains("?")){
actionName = actionName.substring(0, actionName.indexOf("?"));
}
String url = ns + "/" + actionName ;
HttpSession s = req.getSession();
ServletContext sc = s.getServletContext();
Map<String, Right> map = (Map<String, Right>) sc.getAttribute("all_rights_map");
Right r = map.get(url);
if(r == null){
return false ;
}
//公共资源
if(r.isCommon()){
return true ;
}
else{
User user = (User) s.getAttribute("user");
//登录?
if(user == null){
return false ;
}
else{
//userAware
if(action != null
&& action instanceof UserAware){
((UserAware)action).setUser(user);
}
//超级管理员?
if(user.isSuperAdmin()){
return true ;
}
else{
//有权限?
if(user.hasRight(r)){
return true ;
}
else{
return false ;
}
}
}
}
}
IniRightListener
使用监听器:listener. spring listener.
在web服务器启动完成前,spring容器初始化之后,将所有权限,查询出来,存放到application(ServletContext)中.
[html] view plaincopy
/**
* 初始化权限监听器
*/
@SuppressWarnings("rawtypes")
@Component
public class IniRightListener implements ApplicationListener,ServletContextAware{
@Resource
private RightService rs ;
//接受servletContext对象
private ServletContext sc;
public void onApplicationEvent(ApplicationEvent arg0) {
//是否是上下文刷新事件
if(arg0 instanceof ContextRefreshedEvent){
List<Right> list = rs.findAllEntities();
Map<String, Right> map = new HashMap<String, Right>();
for(Right r : list){
map.put(r.getRightUrl(), r);
}
if(sc != null){
sc.setAttribute("all_rights_map", map);
System.out.println("权限初始化完成了!!");
}
}
}
//注入sc
public void setServletContext(ServletContext servletContext) {
//
System.out.println("注入sc");
this.sc = servletContext ;
}
}