使用BigInteger进行权限设计

参考表结构

user

CREATE TABLE `sys_user` (
  `USER_ID` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `USERNAME` varchar(255) DEFAULT NULL,
  `PASSWORD` varchar(255) DEFAULT NULL,
  `NAME` varchar(255) DEFAULT NULL,
  `RIGHTS` varchar(255) DEFAULT NULL,
  `ROLE_ID` text,
  PRIMARY KEY (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

role

CREATE TABLE `sys_role` (
  `ROLE_ID` varchar(100) NOT NULL,
  `ROLE_NAME` varchar(100) DEFAULT NULL,
  `RIGHTS` text, //【通过BigInteger计算】
  `PARENT_ID` varchar(100) DEFAULT NULL, // 角色组操作,0表示角色组
  `TYPE` varchar(11) DEFAULT '1', // 角色的类型
   PRIMARY KEY (`ROLE_ID`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

menu

CREATE TABLE `sys_menu` (
  `MENU_ID` int(11) NOT NULL,
  `MENU_NAME` varchar(255) DEFAULT NULL,
  `MENU_URL` varchar(255) DEFAULT NULL,
  `PARENT_ID` varchar(100) DEFAULT NULL, // 0 为一级菜单
  `MENU_ORDER` varchar(100) DEFAULT NULL,
  `MENU_ICON` varchar(30) DEFAULT NULL,
  `MENU_TYPE` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`MENU_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

说明

首先,从系统界面中设置角色权限关系,将选好的菜单树权限勾选,完成后传到后台,后台通过转成字符串数组来进行设值;使用如下操作返回权限集合BigInteger值

public static BigInteger sumRights(String[] rights){
		BigInteger num = new BigInteger("0");
		for(int i=0; i<rights.length; i++){
			num = num.setBit(Integer.parseInt(rights[i]));
		}
		return num;
}

通过上面方法,返回一个BigInteger,然后将这个数字保存在所属角色的菜单权限字段中(RIGHTS)

注意的是:这里的菜单ID(MENU_ID)必须是数字

最后,检查角色权限时通过把之前存入RIGHTS字段值和菜单ID做对比来判断是否具有该菜单权限,

public static boolean testRights(BigInteger sum,int targetRights){
		return sum.testBit(targetRights);
}

BigInteger使用例子

public class Main {

	public static void main(String[] args) {


        // 用于处理超出了Integer返回的大整数
        BigInteger num = new BigInteger("0");
        num = num.setBit(2);
        num = num.setBit(1);
        num = num.setBit(7);
        
        System.out.println(num);
        System.out.println(num.testBit(2));
        System.out.println(num.testBit(1));
        System.out.println(num.testBit(3));
        System.out.println(num.testBit(7));
        
        num = num.clearBit(7);
        System.out.println(num.testBit(7));
        /**
			134
			true
			true
			false
			true
			false
         */
        
	}
}

使用例子

连接常量

public class Const {
public static final String NO_INTERCEPTOR_PATH = ".*/((login)|(logout)|(code)|(app)|(weixin)|(static)|(main)|(websocket)|(index)|(twoDimensionCode)|(index_two)|(uploadImgs)|(Nozzle)|(plugins)).*"; // 不对匹配该值的访问路径拦截(正则)

登录拦截器

public class LoginHandlerInterceptor extends HandlerInterceptorAdapter {
	
	/** 
	 * 	处理请求之前执行
	 */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
    	
    	// 获取请求连接
        String path = request.getServletPath();
        
        // 判断是否为无需拦截的连接
        if (path.matches(Const.NO_INTERCEPTOR_PATH)) { 
            return true;
        } else { 
        	
            // shiro管理的session
            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();
            User user = (User) session.getAttribute(Const.SESSION_USER); // 获取当前登录的用户
            
            // 判断是否有登录
            if (user != null) {

                // 判断是否拥有当前点击菜单的权限(内部过滤,防止通过url进入跳过菜单权限)
                /**
                 *	根据点击的菜单的xxx.do去菜单中的URL去匹配,当匹配到了此菜单,判断是否有此菜单的权限,没有的话跳转到404页面
                 * 	根据按钮权限,授权按钮(当前点的菜单和角色中各按钮的权限匹对)
                 */
                Boolean b = true;
                
                // 获取当前用户拥有的权限菜单
                List<Menu> menuList = (List) session.getAttribute(Const.SESSION_allmenuList);
                

                path = path.substring(1, path.length());  // /role.do -> role.do
                System.out.println("拦截了::" + path);
                
                for (int i = 0; i < menuList.size(); i++) {
                	
                    for (int j = 0; j < menuList.get(i).getSubMenu().size(); j++) {
                    	
                    	// 判断权限菜单中是否有当前连接的菜单的URL
                        if (menuList.get(i).getSubMenu().get(j).getMENU_URL().split(".do")[0].equals(path.split(".do")[0])) {
                        	
                        	// 没有权限
                            if (!menuList.get(i).getSubMenu().get(j).isHasMenu()) {
                            	// 重定向到登录页面
                                response.sendRedirect(request.getContextPath() + Const.LOGIN);
                                return false;
                            } 
                        }
                    }
                }
                return true;
                
            } else { 
            	// 没有登录,重定向到登录页面 
                response.sendRedirect(request.getContextPath() + Const.LOGIN);
                return false;
            }
        }
    }
}

登录Action

  /**
     * 访问系统首页
     * 第一次访问,{changeMenu}为index
     */
    @RequestMapping(value = "/main/{changeMenu}")
    public ModelAndView login_index(@PathVariable("changeMenu") String changeMenu) {
        ModelAndView mv = this.getModelAndView();
        PageData pd = new PageData();
        pd = this.getPageData();
        try {

            //shiro管理的session
            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();
            User user = (User) session.getAttribute(Const.SESSION_USER); // 获取session中的无角色信息的用户对象
            PageData findUserPd = new PageData();
            findUserPd.put("USER_ID", user.getUSER_ID()); // 保存登录用户id
            
            String roleIds = "";
            PageData userPd = sysUserService.findByUiId(findUserPd); // 根据用户id查询完整的用户信息
            
            if(userPd!=null&&userPd.containsKey("ROLE_ID")){
            	roleIds = userPd.get("ROLE_ID").toString();  // 获取所有角色id
            }
            /*String roleIds = sysUserService.findByUiId(findUserPd)==null?"":sysUserService.findByUiId(findUserPd).get("ROLE_ID").toString();*/
            if (user != null) {
            	
            	/** 带有角色信息的用户对象 */
                User userr = (User) session.getAttribute(Const.SESSION_USERROL); 
                
                if (null == userr) { // 第一次为null
                	
                	if(roleIds!=""&&roleIds.contains(",")){ /** 有一个或者多个角色 */
                		List<Role> roleList = new ArrayList<Role>();
                		String[] roles = roleIds.split(",");
                		for(String role : roles){
                			/*findUserPd.put("ROLE_ID", role);
                			user = sysUserService.getUserAndRoleByPd(findUserPd);*/
                			Role roleBean = roleService.getRoleById(role);
                			roleList.add(roleBean);
                		}
                		user.setRoleList(roleList);
                		
                	}else{ /** 根据用户id查询角色信息 */
                		List<Role> roleList = new ArrayList<Role>();
                        user = sysUserService.getUserAndRoleById(user.getUSER_ID());
                        roleList.add(user.getRole());
                        user.setRoleList(roleList);
                	}
                    session.setAttribute(Const.SESSION_USERROL, user);
                } else {
                    user = userr;
                }
                
                String roleRights=""; // 角色权限
                String roleNames=""; // 角色名称
            	List<Role> roleList = user.getRoleList(); // 获取所有用户角色
            	
            	// 设置 角色权限 和 角色名称
            	if(roleList!=null&&roleList.get(0)!=null){
                	for(Role role : roleList){
                		// 连接字符串
                        roleRights += role != null ? role.getRIGHTS()+"," : "";
                        roleNames += role!= null ? role.getROLE_NAME()+"," : "";
                	}
                	// 减去最后的符号
                	roleRights = roleRights.substring(0,roleRights.length()-1);
                	roleNames = roleNames.substring(0,roleNames.length()-1);
            	}
            	
            	/** 保存一份到session */
                //避免每次拦截用户操作时查询数据库,以下将用户所属角色权限、用户权限限都存入session
                session.setAttribute(Const.SESSION_ROLE_RIGHTS, roleRights);        //将当前用户的权限存入session
                session.setAttribute(Const.SESSION_USERNAME, user.getUSERNAME());    //放入用户名
                
                /** 保存一份到PageData */
                pd.put("USERNAME", user.getUSERNAME());
                /*pd.put("USERROLE", user.getRole().getROLE_NAME());*/
                pd.put("USERROLE", roleNames);
                pd.put("AVATAR", user.getAVATAR());
                pd.put("NAME", user.getNAME());
                pd.put("deptname", userPd.getString("deptname"));
                
                //获取用户头像
                PageData uPageData = new PageData();
                uPageData = sysUserService.getUserAvatarById(user.getUSER_ID());
                if (uPageData != null) {
                    if (uPageData.get("AVATAR") != null) {
                        pd.put("AVATAR", uPageData.get("AVATAR"));
                    }
                }
                
                List<Menu> allmenuList = new ArrayList<Menu>();
                if (null == session.getAttribute(Const.SESSION_allmenuList)) {
                	
                    /**
                     *  获取所有菜单 - 父级菜单
                     */
                    allmenuList = menuService.listAllMenu();
                    if (Tools.notEmpty(roleRights)) {
                        
                    	// 遍历当前用户的所有角色
                    	for(Role role : roleList){
                    		
                    		// 遍历所有菜单
                            for (Menu menu : allmenuList) { 
                            	
                            	/**
                            	 * 判断是否拥有当前菜单权限
                            	 */
                            	if(!menu.isHasMenu()){  // menu.isHasMenu()默认为false
                            		// 判断当前用户拥有的角色,角色是否拥有对应菜单的权限并设置到菜单中,用于保存到session
                                    menu.setHasMenu(RightsHelper.testRights(role.getRIGHTS(), menu.getMENU_ID()));
                                }

                            	/**
                            	 * 判断是否有子菜单的权限
                            	 */
                            	// 经过上一个IF过后,如果有权限,那么继续判断该父级菜单下的子菜单是否也有权限方法
                            	// 因为可能出现父级菜单可以访问,但该父级菜单下的某个子菜单不能访问的可能性
                                if (menu.isHasMenu()) {  
                                    for (Menu sub :  menu.getSubMenu()) {
                                        if(!sub.isHasMenu()){
                                            sub.setHasMenu(RightsHelper.testRights(role.getRIGHTS(), sub.getMENU_ID()));
                                        }
                                    }
                                }
                            }
                        }
                    }
                    session.setAttribute(Const.SESSION_allmenuList, allmenuList);            //菜单权限放入session中
                } else {
                    allmenuList = (List<Menu>) session.getAttribute(Const.SESSION_allmenuList);
                }
//......................
原文地址:https://www.cnblogs.com/tandi19960505/p/9863615.html