优化多角色数据权限匹配规则

This commit is contained in:
RuoYi 2022-08-21 22:44:27 +08:00
parent 41824c1528
commit fa177f58a5
16 changed files with 175 additions and 30 deletions

View File

@ -12,6 +12,11 @@ public class UserConstants
*/ */
public static final String SYS_USER = "SYS_USER"; public static final String SYS_USER = "SYS_USER";
/**
* ss标记的权限字符
*/
public static final String SS_PERMISSION = "SS_PERMISSION";
/** 正常状态 */ /** 正常状态 */
public static final String NORMAL = "0"; public static final String NORMAL = "0";

View File

@ -10,6 +10,7 @@ import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.aspectj.lang.annotation.DataScope; import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
import com.ruoyi.framework.security.LoginUser; import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.security.context.PermissionContextHolder;
import com.ruoyi.framework.web.domain.BaseEntity; import com.ruoyi.framework.web.domain.BaseEntity;
import com.ruoyi.project.system.domain.SysRole; import com.ruoyi.project.system.domain.SysRole;
import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.SysUser;
@ -70,8 +71,9 @@ public class DataScopeAspect
// 如果是超级管理员则不过滤数据 // 如果是超级管理员则不过滤数据
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{ {
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias()); controllerDataScope.userAlias(), permission);
} }
} }
} }
@ -83,8 +85,9 @@ public class DataScopeAspect
* @param user 用户 * @param user 用户
* @param deptAlias 部门别名 * @param deptAlias 部门别名
* @param userAlias 用户别名 * @param userAlias 用户别名
* @param permission 权限字符
*/ */
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
{ {
StringBuilder sqlString = new StringBuilder(); StringBuilder sqlString = new StringBuilder();
List<String> conditions = new ArrayList<String>(); List<String> conditions = new ArrayList<String>();
@ -96,6 +99,10 @@ public class DataScopeAspect
{ {
continue; continue;
} }
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions()) && !role.getPermissions().contains(permission))
{
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope)) if (DATA_SCOPE_ALL.equals(dataScope))
{ {
sqlString = new StringBuilder(); sqlString = new StringBuilder();
@ -114,7 +121,7 @@ public class DataScopeAspect
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{ {
sqlString.append(StringUtils.format( sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or FIND_IN_SET ( {} ,ancestors ) <> 0 )",
deptAlias, user.getDeptId(), user.getDeptId())); deptAlias, user.getDeptId(), user.getDeptId()));
} }
else if (DATA_SCOPE_SELF.equals(dataScope)) else if (DATA_SCOPE_SELF.equals(dataScope))

View File

@ -25,4 +25,9 @@ public @interface DataScope
* 用户表的别名 * 用户表的别名
*/ */
public String userAlias() default ""; public String userAlias() default "";
/**
* 权限字符如不填默认会自动根据注解获取
*/
public String permission() default "";
} }

View File

@ -0,0 +1,21 @@
package com.ruoyi.framework.security.context;
/**
* 权限信息
*
* @author ruoyi
*/
public class PermissionContextHolder
{
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setContext(String permission)
{
contextHolder.set(permission);
}
public static String getContext()
{
return contextHolder.get();
}
}

View File

@ -6,6 +6,7 @@ import org.springframework.util.CollectionUtils;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.security.LoginUser; import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.security.context.PermissionContextHolder;
import com.ruoyi.project.system.domain.SysRole; import com.ruoyi.project.system.domain.SysRole;
/** /**
@ -43,6 +44,7 @@ public class PermissionService
{ {
return false; return false;
} }
PermissionContextHolder.setContext(permission);
return hasPermissions(loginUser.getPermissions(), permission); return hasPermissions(loginUser.getPermissions(), permission);
} }

View File

@ -1,9 +1,11 @@
package com.ruoyi.framework.security.service; package com.ruoyi.framework.security.service;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.project.system.domain.SysRole;
import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.service.ISysMenuService; import com.ruoyi.project.system.service.ISysMenuService;
import com.ruoyi.project.system.service.ISysRoleService; import com.ruoyi.project.system.service.ISysRoleService;
@ -58,9 +60,23 @@ public class SysPermissionService
perms.add("*:*:*"); perms.add("*:*:*");
} }
else else
{
List<SysRole> roles = user.getRoles();
if (!roles.isEmpty() && roles.size() > 1)
{
// 多角色设置permissions属性以便数据权限匹配权限
for (SysRole role : roles)
{
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
role.setPermissions(rolePerms);
perms.addAll(rolePerms);
}
}
else
{ {
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
} }
}
return perms; return perms;
} }
} }

View File

@ -78,29 +78,6 @@ public class SysDeptController extends BaseController
return AjaxResult.success(deptService.selectDeptById(deptId)); return AjaxResult.success(deptService.selectDeptById(deptId));
} }
/**
* 获取部门下拉树列表
*/
@GetMapping("/treeselect")
public AjaxResult treeselect(SysDept dept)
{
List<SysDept> depts = deptService.selectDeptList(dept);
return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
}
/**
* 加载对应角色部门列表树
*/
@GetMapping(value = "/roleDeptTreeselect/{roleId}")
public AjaxResult roleDeptTreeselect(@PathVariable("roleId") Long roleId)
{
List<SysDept> depts = deptService.selectDeptList(new SysDept());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.buildDeptTreeSelect(depts));
return ajax;
}
/** /**
* 新增部门 * 新增部门
*/ */

View File

@ -24,9 +24,11 @@ import com.ruoyi.framework.security.service.TokenService;
import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo; import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysRole; import com.ruoyi.project.system.domain.SysRole;
import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.domain.SysUserRole; import com.ruoyi.project.system.domain.SysUserRole;
import com.ruoyi.project.system.service.ISysDeptService;
import com.ruoyi.project.system.service.ISysRoleService; import com.ruoyi.project.system.service.ISysRoleService;
import com.ruoyi.project.system.service.ISysUserService; import com.ruoyi.project.system.service.ISysUserService;
@ -51,6 +53,9 @@ public class SysRoleController extends BaseController
@Autowired @Autowired
private ISysUserService userService; private ISysUserService userService;
@Autowired
private ISysDeptService deptService;
@PreAuthorize("@ss.hasPermi('system:role:list')") @PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list") @GetMapping("/list")
public TableDataInfo list(SysRole role) public TableDataInfo list(SysRole role)
@ -242,4 +247,17 @@ public class SysRoleController extends BaseController
roleService.checkRoleDataScope(roleId); roleService.checkRoleDataScope(roleId);
return toAjax(roleService.insertAuthUsers(roleId, userIds)); return toAjax(roleService.insertAuthUsers(roleId, userIds));
} }
/**
* 获取对应角色部门树列表
*/
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping(value = "/deptTree/{roleId}")
public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
{
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
return ajax;
}
} }

View File

@ -25,8 +25,10 @@ import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController; import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo; import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysRole; import com.ruoyi.project.system.domain.SysRole;
import com.ruoyi.project.system.domain.SysUser; import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.service.ISysDeptService;
import com.ruoyi.project.system.service.ISysPostService; import com.ruoyi.project.system.service.ISysPostService;
import com.ruoyi.project.system.service.ISysRoleService; import com.ruoyi.project.system.service.ISysRoleService;
import com.ruoyi.project.system.service.ISysUserService; import com.ruoyi.project.system.service.ISysUserService;
@ -46,6 +48,9 @@ public class SysUserController extends BaseController
@Autowired @Autowired
private ISysRoleService roleService; private ISysRoleService roleService;
@Autowired
private ISysDeptService deptService;
@Autowired @Autowired
private ISysPostService postService; private ISysPostService postService;
@ -234,4 +239,14 @@ public class SysUserController extends BaseController
userService.insertUserAuth(userId, roleIds); userService.insertUserAuth(userId, roleIds);
return success(); return success();
} }
/**
* 获取部门树列表
*/
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/deptTree")
public AjaxResult deptTree(SysDept dept)
{
return AjaxResult.success(deptService.selectDeptTreeList(dept));
}
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.project.system.domain; package com.ruoyi.project.system.domain;
import java.util.Set;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
@ -59,6 +60,9 @@ public class SysRole extends BaseEntity
/** 部门组(数据权限) */ /** 部门组(数据权限) */
private Long[] deptIds; private Long[] deptIds;
/** 角色菜单权限 */
private Set<String> permissions;
public SysRole() public SysRole()
{ {
@ -204,6 +208,16 @@ public class SysRole extends BaseEntity
this.deptIds = deptIds; this.deptIds = deptIds;
} }
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

View File

@ -42,6 +42,14 @@ public interface SysMenuMapper
*/ */
public List<String> selectMenuPermsByUserId(Long userId); public List<String> selectMenuPermsByUserId(Long userId);
/**
* 根据角色ID查询权限
*
* @param roleId 角色ID
* @return 权限列表
*/
public List<String> selectMenuPermsByRoleId(Long roleId);
/** /**
* 根据用户ID查询菜单 * 根据用户ID查询菜单
* *

View File

@ -19,6 +19,14 @@ public interface ISysDeptService
*/ */
public List<SysDept> selectDeptList(SysDept dept); public List<SysDept> selectDeptList(SysDept dept);
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
public List<TreeSelect> selectDeptTreeList(SysDept dept);
/** /**
* 构建前端所需要树结构 * 构建前端所需要树结构
* *

View File

@ -38,6 +38,14 @@ public interface ISysMenuService
*/ */
public Set<String> selectMenuPermsByUserId(Long userId); public Set<String> selectMenuPermsByUserId(Long userId);
/**
* 根据角色ID查询权限
*
* @param roleId 角色ID
* @return 权限列表
*/
public Set<String> selectMenuPermsByRoleId(Long roleId);
/** /**
* 根据用户ID查询菜单树信息 * 根据用户ID查询菜单树信息
* *

View File

@ -48,6 +48,19 @@ public class SysDeptServiceImpl implements ISysDeptService
return deptMapper.selectDeptList(dept); return deptMapper.selectDeptList(dept);
} }
/**
* 查询部门树结构信息
*
* @param dept 部门信息
* @return 部门树信息集合
*/
@Override
public List<TreeSelect> selectDeptTreeList(SysDept dept)
{
List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
return buildDeptTreeSelect(depts);
}
/** /**
* 构建前端所需要树结构 * 构建前端所需要树结构
* *

View File

@ -100,6 +100,27 @@ public class SysMenuServiceImpl implements ISysMenuService
return permsSet; return permsSet;
} }
/**
* 根据角色ID查询权限
*
* @param roleId 角色ID
* @return 权限列表
*/
@Override
public Set<String> selectMenuPermsByRoleId(Long roleId)
{
List<String> perms = menuMapper.selectMenuPermsByRoleId(roleId);
Set<String> permsSet = new HashSet<>();
for (String perm : perms)
{
if (StringUtils.isNotEmpty(perm))
{
permsSet.addAll(Arrays.asList(perm.trim().split(",")));
}
}
return permsSet;
}
/** /**
* 根据用户ID查询菜单 * 根据用户ID查询菜单
* *

View File

@ -111,6 +111,13 @@
where m.status = '0' and r.status = '0' and ur.user_id = #{userId} where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
</select> </select>
<select id="selectMenuPermsByRoleId" parameterType="Long" resultType="String">
select distinct m.perms
from sys_menu m
left join sys_role_menu rm on m.menu_id = rm.menu_id
where m.status = '0' and rm.role_id = #{roleId}
</select>
<select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult"> <select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult">
<include refid="selectMenuVo"/> <include refid="selectMenuVo"/>
where menu_id = #{menuId} where menu_id = #{menuId}