参考表结构
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);
}
//......................