• 使用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);
                    }
    //......................
    
  • 相关阅读:
    利用avalon 实现一个简单的成绩单
    有关less 处理@arguments的一些高级技巧
    迷你MVVM框架 avalonjs 0.9发布
    IE9-10 option BUG
    判定元素正在插入到DOM树——DOMNodeInsertedIntoDocument
    迷你MVVM框架 avalonjs 0.85发布
    机器学习研究与开发平台的选择
    JS生成指定范围内的随机数(支持随机小数)
    DDD领域驱动设计 ---- 系列文章
    序列化效率比拼——谁是最后的赢家avaScriptSerializer方式、DataContract方式、Newtonsoft.Json
  • 原文地址:https://www.cnblogs.com/tandi19960505/p/9863615.html
Copyright © 2020-2023  润新知