1
接口入手 我们发现,若依的getInfo接口获取了用户的roles与permissions以及用户的基本信息,我们来研究一下其获取逻辑与sql,从而尝试从接口与sql研究其权限表设计结构。
getInfo接口 在Controller中,其代码实现为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @GetMapping("getInfo") public AjaxResult getInfo () { SysUser user = SecurityUtils.getLoginUser().getUser(); Set<String> roles = permissionService.getRolePermission(user); Set<String> permissions = permissionService.getMenuPermission(user); AjaxResult ajax = AjaxResult.success(); ajax.put("user" , user); ajax.put("roles" , roles); ajax.put("permissions" , permissions); return ajax; }
我们展开看一下其中的角色集合与权限集合方法。
1 2 3 4 Set<String> roles = permissionService.getRolePermission(user); Set<String> permissions = permissionService.getMenuPermission(user);
getRolePermission 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public Set<String> getRolePermission (SysUser user) { Set<String> roles = new HashSet <String>(); if (user.isAdmin()) { roles.add("admin" ); } else { roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId())); } return roles; }
对于管理员,仅需要添加admin
即可,否则则需要按照用户id去查询用户权限,我们再次深入,展开selectRolePermissionByUserId
方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Override public Set<String> selectRolePermissionByUserId (Long userId) { List<SysRole> perms = roleMapper.selectRolePermissionByUserId(userId); Set<String> permsSet = new HashSet <>(); for (SysRole perm : perms) { if (StringUtils.isNotNull(perm)) { permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split("," ))); } } return permsSet; }
方法第一句调用mapper中的方法,实际是执行sql查询,我们看一下其执行的sql:
1 2 3 4 5 6 7 select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly, r.status, r.del_flag, r.create_time, r.remark from sys_role r left join sys_user_role ur on ur.role_id = r.role_id left join sys_user u on u.user_id = ur.user_id left join sys_dept d on u.dept_id = d.dept_id WHERE r.del_flag = '0' and ur.user_id = #{userId}
由此,得到其角色表主表为sys_role,角色与用户关联表为sys_user_role。从表命名上我们也能看出一二来。
同样的,我们展开权限方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public Set<String> getMenuPermission (SysUser user) { Set<String> perms = new HashSet <String>(); if (user.isAdmin()) { perms.add("*:*:*" ); } else { perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); } return perms; }
若是admin,则只添加*:*:*
,否则执行方法:selectMenuPermsByUserId,我们再次深入展开:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Override public Set<String> selectMenuPermsByUserId (Long userId) { List<String> perms = menuMapper.selectMenuPermsByUserId(userId); Set<String> permsSet = new HashSet <>(); for (String perm : perms) { if (StringUtils.isNotEmpty(perm)) { permsSet.addAll(Arrays.asList(perm.trim().split("," ))); } } return permsSet; }
同样的,关键语句在于sql查询selectMenuPermsByUserId:
1 2 3 4 5 6 select distinct m.perms from sys_menu m left join sys_role_menu rm on m.menu_id = rm.menu_id left join sys_user_role ur on rm.role_id = ur.role_id left join sys_role r on r.role_id = ur.role_id where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
我们发现,若依系统中,获取的权限实际上都属于“菜单”的权限,注意,这里的菜单包括实际意义的菜单以及菜单中的按钮,即包括下图两个东西:
获取权限,从其执行的sql来看,其实际逻辑为:
用户->用户的角色->角色关联的菜单->返回菜单的权限字符。即:
sys_user -> sys_user_role -> sys_role_menu -> sys_menu
这样避免了空权限(我所指的空权限是有此权限而没有实际含义),即每个权限都有对应的菜单或按钮。