Bladeren bron

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

RuoYi 2 jaren geleden
bovenliggende
commit
9b3767a954
21 gewijzigde bestanden met toevoegingen van 203 en 66 verwijderingen
  1. 0 23
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
  2. 21 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
  3. 15 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
  4. 5 0
      ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
  5. 5 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
  6. 15 1
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
  7. 10 3
      ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
  8. 21 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java
  9. 2 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
  10. 17 1
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java
  11. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
  12. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
  13. 8 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
  14. 13 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
  15. 21 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
  16. 8 0
      ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
  17. 0 16
      ruoyi-ui/src/api/system/dept.js
  18. 9 1
      ruoyi-ui/src/api/system/role.js
  19. 8 0
      ruoyi-ui/src/api/system/user.js
  20. 5 12
      ruoyi-ui/src/views/system/role/index.vue
  21. 4 7
      ruoyi-ui/src/views/system/user/index.vue

+ 0 - 23
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java

@@ -78,29 +78,6 @@ public class SysDeptController extends BaseController
         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;
-    }
-
     /**
      * 新增部门
      */

+ 21 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java

@@ -17,6 +17,7 @@ import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
@@ -27,6 +28,7 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.service.SysPermissionService;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.service.ISysDeptService;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.service.ISysUserService;
 
@@ -44,13 +46,16 @@ public class SysRoleController extends BaseController
 
     @Autowired
     private TokenService tokenService;
-    
+
     @Autowired
     private SysPermissionService permissionService;
-    
+
     @Autowired
     private ISysUserService userService;
 
+    @Autowired
+    private ISysDeptService deptService;
+
     @PreAuthorize("@ss.hasPermi('system:role:list')")
     @GetMapping("/list")
     public TableDataInfo list(SysRole role)
@@ -242,4 +247,18 @@ public class SysRoleController extends BaseController
         roleService.checkRoleDataScope(roleId);
         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;
+    }
+
 }

+ 15 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java

@@ -20,6 +20,7 @@ import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.page.TableDataInfo;
@@ -27,6 +28,7 @@ import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.service.ISysDeptService;
 import com.ruoyi.system.service.ISysPostService;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.service.ISysUserService;
@@ -46,6 +48,9 @@ public class SysUserController extends BaseController
     @Autowired
     private ISysRoleService roleService;
 
+    @Autowired
+    private ISysDeptService deptService;
+
     @Autowired
     private ISysPostService postService;
 
@@ -234,4 +239,14 @@ public class SysUserController extends BaseController
         userService.insertUserAuth(userId, roleIds);
         return success();
     }
+
+    /**
+     * 获取部门树列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:list')")
+    @GetMapping("/deptTree")
+    public AjaxResult deptTree(SysDept dept)
+    {
+        return AjaxResult.success(deptService.selectDeptTreeList(dept));
+    }
 }

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java

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

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java

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

+ 15 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java

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

+ 10 - 3
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java

@@ -11,8 +11,9 @@ import com.ruoyi.common.core.domain.BaseEntity;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.context.PermissionContextHolder;
 
 /**
  * 数据过滤处理
@@ -70,8 +71,9 @@ public class DataScopeAspect
             // 如果是超级管理员,则不过滤数据
             if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
             {
+                String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
                 dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
-                        controllerDataScope.userAlias());
+                        controllerDataScope.userAlias(), permission);
             }
         }
     }
@@ -83,8 +85,9 @@ public class DataScopeAspect
      * @param user 用户
      * @param deptAlias 部门别名
      * @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();
         List<String> conditions = new ArrayList<String>();
@@ -96,6 +99,10 @@ public class DataScopeAspect
             {
                 continue;
             }
+            if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions()) && !role.getPermissions().contains(permission))
+            {
+                continue;
+            }
             if (DATA_SCOPE_ALL.equals(dataScope))
             {
                 sqlString = new StringBuilder();

+ 21 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java

@@ -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();
+    }
+}

+ 2 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java

@@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.context.PermissionContextHolder;
 
 /**
  * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母
@@ -43,6 +44,7 @@ public class PermissionService
         {
             return false;
         }
+        PermissionContextHolder.setContext(permission);
         return hasPermissions(loginUser.getPermissions(), permission);
     }
 

+ 17 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java

@@ -1,9 +1,11 @@
 package com.ruoyi.framework.web.service;
 
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.system.service.ISysMenuService;
 import com.ruoyi.system.service.ISysRoleService;
@@ -59,7 +61,21 @@ public class SysPermissionService
         }
         else
         {
-            perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+            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()));
+            }
         }
         return perms;
     }

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java

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

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java

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

+ 8 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java

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

+ 13 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java

@@ -48,6 +48,19 @@ public class SysDeptServiceImpl implements ISysDeptService
         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);
+    }
+
     /**
      * 构建前端所需要树结构
      * 

+ 21 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java

@@ -100,6 +100,27 @@ public class SysMenuServiceImpl implements ISysMenuService
         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查询菜单
      * 

+ 8 - 0
ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml

@@ -111,6 +111,14 @@
 		where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
 	</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">
 		<include refid="selectMenuVo"/>
 		where menu_id = #{menuId}

+ 0 - 16
ruoyi-ui/src/api/system/dept.js

@@ -25,22 +25,6 @@ export function getDept(deptId) {
   })
 }
 
-// 查询部门下拉树结构
-export function treeselect() {
-  return request({
-    url: '/system/dept/treeselect',
-    method: 'get'
-  })
-}
-
-// 根据角色ID查询部门树结构
-export function roleDeptTreeselect(roleId) {
-  return request({
-    url: '/system/dept/roleDeptTreeselect/' + roleId,
-    method: 'get'
-  })
-}
-
 // 新增部门
 export function addDept(data) {
   return request({

+ 9 - 1
ruoyi-ui/src/api/system/role.js

@@ -108,4 +108,12 @@ export function authUserSelectAll(data) {
     method: 'put',
     params: data
   })
-}
+}
+
+// 根据角色ID查询部门树结构
+export function deptTreeSelect(roleId) {
+  return request({
+    url: '/system/role/deptTree/' + roleId,
+    method: 'get'
+  })
+}

+ 8 - 0
ruoyi-ui/src/api/system/user.js

@@ -125,3 +125,11 @@ export function updateAuthRole(data) {
     params: data
   })
 }
+
+// 查询部门下拉树结构
+export function deptTreeSelect() {
+  return request({
+    url: '/system/user/deptTree',
+    method: 'get'
+  })
+}

+ 5 - 12
ruoyi-ui/src/views/system/role/index.vue

@@ -254,9 +254,8 @@
 </template>
 
 <script>
-import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus } from "@/api/system/role";
+import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role";
 import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu";
-import { treeselect as deptTreeselect, roleDeptTreeselect } from "@/api/system/dept";
 
 export default {
   name: "Role",
@@ -364,12 +363,6 @@ export default {
         this.menuOptions = response.data;
       });
     },
-    /** 查询部门树结构 */
-    getDeptTreeselect() {
-      deptTreeselect().then(response => {
-        this.deptOptions = response.data;
-      });
-    },
     // 所有菜单节点数据
     getMenuAllCheckedKeys() {
       // 目前被选中的菜单节点
@@ -396,8 +389,8 @@ export default {
       });
     },
     /** 根据角色ID查询部门树结构 */
-    getRoleDeptTreeselect(roleId) {
-      return roleDeptTreeselect(roleId).then(response => {
+    getDeptTree(roleId) {
+      return deptTreeSelect(roleId).then(response => {
         this.deptOptions = response.depts;
         return response;
       });
@@ -543,12 +536,12 @@ export default {
     /** 分配数据权限操作 */
     handleDataScope(row) {
       this.reset();
-      const roleDeptTreeselect = this.getRoleDeptTreeselect(row.roleId);
+      const deptTreeSelect = this.getDeptTree(row.roleId);
       getRole(row.roleId).then(response => {
         this.form = response.data;
         this.openDataScope = true;
         this.$nextTick(() => {
-          roleDeptTreeselect.then(res => {
+          deptTreeSelect.then(res => {
             this.$refs.dept.setCheckedKeys(res.checkedKeys);
           });
         });

+ 4 - 7
ruoyi-ui/src/views/system/user/index.vue

@@ -342,9 +342,8 @@
 </template>
 
 <script>
-import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus } from "@/api/system/user";
+import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user";
 import { getToken } from "@/utils/auth";
-import { treeselect } from "@/api/system/dept";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 
@@ -462,7 +461,7 @@ export default {
   },
   created() {
     this.getList();
-    this.getTreeselect();
+    this.getDeptTree();
     this.getConfigKey("sys.user.initPassword").then(response => {
       this.initPassword = response.msg;
     });
@@ -479,8 +478,8 @@ export default {
       );
     },
     /** 查询部门下拉树结构 */
-    getTreeselect() {
-      treeselect().then(response => {
+    getDeptTree() {
+      deptTreeSelect().then(response => {
         this.deptOptions = response.data;
       });
     },
@@ -561,7 +560,6 @@ export default {
     /** 新增按钮操作 */
     handleAdd() {
       this.reset();
-      this.getTreeselect();
       getUser().then(response => {
         this.postOptions = response.posts;
         this.roleOptions = response.roles;
@@ -573,7 +571,6 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      this.getTreeselect();
       const userId = row.userId || this.ids;
       getUser(userId).then(response => {
         this.form = response.data;