From a36dc6635f92b1a6a5ea43c801f028dea08a7f0b Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: 星期日, 21 八月 2022 22:44:46 +0800
Subject: [PATCH] 优化多角色数据权限匹配规则

---
 src/main/java/com/ruoyi/project/system/service/ISysDeptService.java             |    8 ++
 src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java     |   21 +++++
 src/main/java/com/ruoyi/common/constant/UserConstants.java                      |    5 +
 src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java    |   18 ++++
 src/main/java/com/ruoyi/project/system/controller/SysRoleController.java        |   20 ++++
 src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java                  |   11 ++
 src/main/java/com/ruoyi/project/system/controller/SysDeptController.java        |   23 -----
 src/main/resources/mybatis/system/SysMenuMapper.xml                             |    7 +
 src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java |   21 +++++
 src/main/java/com/ruoyi/project/system/domain/SysRole.java                      |   16 +++
 src/main/java/com/ruoyi/project/system/service/ISysMenuService.java             |    8 ++
 src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java                |    8 ++
 src/main/java/com/ruoyi/project/system/controller/SysUserController.java        |   17 ++++
 src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java     |   13 +++
 src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java        |    5 +
 src/main/java/com/ruoyi/framework/security/service/PermissionService.java       |    2 
 16 files changed, 174 insertions(+), 29 deletions(-)

diff --git a/src/main/java/com/ruoyi/common/constant/UserConstants.java b/src/main/java/com/ruoyi/common/constant/UserConstants.java
index c6c7797..737c9d5 100644
--- a/src/main/java/com/ruoyi/common/constant/UserConstants.java
+++ b/src/main/java/com/ruoyi/common/constant/UserConstants.java
@@ -12,6 +12,11 @@
      */
     public static final String SYS_USER = "SYS_USER";
 
+    /**
+     * ss鏍囪鐨勬潈闄愬瓧绗�
+     */
+    public static final String SS_PERMISSION = "SS_PERMISSION";
+
     /** 姝e父鐘舵�� */
     public static final String NORMAL = "0";
 
diff --git a/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
index 9e0caea..b0c332b 100644
--- a/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
+++ b/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
@@ -10,6 +10,7 @@
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.aspectj.lang.annotation.DataScope;
 import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.security.context.PermissionContextHolder;
 import com.ruoyi.framework.web.domain.BaseEntity;
 import com.ruoyi.project.system.domain.SysRole;
 import com.ruoyi.project.system.domain.SysUser;
@@ -70,8 +71,9 @@
             // 濡傛灉鏄秴绾х鐞嗗憳锛屽垯涓嶈繃婊ゆ暟鎹�
             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 @@
      * @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 @@
             {
                 continue;
             }
+            if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions()) && !role.getPermissions().contains(permission))
+            {
+                continue;
+            }
             if (DATA_SCOPE_ALL.equals(dataScope))
             {
                 sqlString = new StringBuilder();
diff --git a/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java b/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java
index 5e4cc9c..3eefec8 100644
--- a/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java
+++ b/src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java
@@ -25,4 +25,9 @@
      * 鐢ㄦ埛琛ㄧ殑鍒悕
      */
     public String userAlias() default "";
+
+    /**
+     * 鏉冮檺瀛楃锛堝涓嶅~榛樿浼氳嚜鍔ㄦ牴鎹敞瑙h幏鍙栵級
+     */
+    public String permission() default "";
 }
diff --git a/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java b/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java
new file mode 100644
index 0000000..fcd93b6
--- /dev/null
+++ b/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();
+    }
+}
diff --git a/src/main/java/com/ruoyi/framework/security/service/PermissionService.java b/src/main/java/com/ruoyi/framework/security/service/PermissionService.java
index 2fa1e5f..a27b798 100644
--- a/src/main/java/com/ruoyi/framework/security/service/PermissionService.java
+++ b/src/main/java/com/ruoyi/framework/security/service/PermissionService.java
@@ -6,6 +6,7 @@
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.security.context.PermissionContextHolder;
 import com.ruoyi.project.system.domain.SysRole;
 
 /**
@@ -43,6 +44,7 @@
         {
             return false;
         }
+        PermissionContextHolder.setContext(permission);
         return hasPermissions(loginUser.getPermissions(), permission);
     }
 
diff --git a/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java b/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java
index 021e9a5..0d4b280 100644
--- a/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java
+++ b/src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java
@@ -1,9 +1,11 @@
 package com.ruoyi.framework.security.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.project.system.domain.SysRole;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.service.ISysMenuService;
 import com.ruoyi.project.system.service.ISysRoleService;
@@ -59,7 +61,21 @@
         }
         else
         {
-            perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+            List<SysRole> roles = user.getRoles();
+            if (!roles.isEmpty() && roles.size() > 1)
+            {
+                // 澶氳鑹茶缃畃ermissions灞炴�э紝浠ヤ究鏁版嵁鏉冮檺鍖归厤鏉冮檺
+                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;
     }
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java b/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
index 953747c..793b0db 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysDeptController.java
@@ -79,29 +79,6 @@
     }
 
     /**
-     * 鑾峰彇閮ㄩ棬涓嬫媺鏍戝垪琛�
-     */
-    @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;
-    }
-
-    /**
      * 鏂板閮ㄩ棬
      */
     @PreAuthorize("@ss.hasPermi('system:dept:add')")
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java b/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
index 30f656e..7bdd909 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysRoleController.java
@@ -24,9 +24,11 @@
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 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.SysUser;
 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.ISysUserService;
 
@@ -50,6 +52,9 @@
     
     @Autowired
     private ISysUserService userService;
+
+    @Autowired
+    private ISysDeptService deptService;
 
     @PreAuthorize("@ss.hasPermi('system:role:list')")
     @GetMapping("/list")
@@ -242,4 +247,17 @@
         roleService.checkRoleDataScope(roleId);
         return toAjax(roleService.insertAuthUsers(roleId, userIds));
     }
-}
\ No newline at end of file
+
+    /**
+     * 鑾峰彇瀵瑰簲瑙掕壊閮ㄩ棬鏍戝垪琛�
+     */
+    @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;
+    }
+}
diff --git a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java b/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
index a79fed5..e21fadf 100644
--- a/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
+++ b/src/main/java/com/ruoyi/project/system/controller/SysUserController.java
@@ -25,8 +25,10 @@
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 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.SysUser;
+import com.ruoyi.project.system.service.ISysDeptService;
 import com.ruoyi.project.system.service.ISysPostService;
 import com.ruoyi.project.system.service.ISysRoleService;
 import com.ruoyi.project.system.service.ISysUserService;
@@ -45,6 +47,9 @@
 
     @Autowired
     private ISysRoleService roleService;
+
+    @Autowired
+    private ISysDeptService deptService;
 
     @Autowired
     private ISysPostService postService;
@@ -234,4 +239,14 @@
         userService.insertUserAuth(userId, roleIds);
         return success();
     }
-}
\ No newline at end of file
+
+    /**
+     * 鑾峰彇閮ㄩ棬鏍戝垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:list')")
+    @GetMapping("/deptTree")
+    public AjaxResult deptTree(SysDept dept)
+    {
+        return AjaxResult.success(deptService.selectDeptTreeList(dept));
+    }
+}
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysRole.java b/src/main/java/com/ruoyi/project/system/domain/SysRole.java
index c947414..9326ac4 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysRole.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysRole.java
@@ -1,5 +1,6 @@
 package com.ruoyi.project.system.domain;
 
+import java.util.Set;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.Size;
 import org.apache.commons.lang3.builder.ToStringBuilder;
@@ -58,6 +59,9 @@
 
     /** 閮ㄩ棬缁勶紙鏁版嵁鏉冮檺锛� */
     private Long[] deptIds;
+
+    /** 瑙掕壊鑿滃崟鏉冮檺 */
+    private Set<String> permissions;
 
     public SysRole()
     {
@@ -203,7 +207,17 @@
     {
         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)
diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java
index d7ebd32..3a0857d 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java
@@ -43,6 +43,14 @@
     public List<String> selectMenuPermsByUserId(Long userId);
 
     /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    public List<String> selectMenuPermsByRoleId(Long roleId);
+
+    /**
      * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
      * 
      * @return 鑿滃崟鍒楄〃
diff --git a/src/main/java/com/ruoyi/project/system/service/ISysDeptService.java b/src/main/java/com/ruoyi/project/system/service/ISysDeptService.java
index 02a89b5..9c83483 100644
--- a/src/main/java/com/ruoyi/project/system/service/ISysDeptService.java
+++ b/src/main/java/com/ruoyi/project/system/service/ISysDeptService.java
@@ -20,6 +20,14 @@
     public List<SysDept> selectDeptList(SysDept dept);
 
     /**
+     * 鏌ヨ閮ㄩ棬鏍戠粨鏋勪俊鎭�
+     * 
+     * @param dept 閮ㄩ棬淇℃伅
+     * @return 閮ㄩ棬鏍戜俊鎭泦鍚�
+     */
+    public List<TreeSelect> selectDeptTreeList(SysDept dept);
+
+    /**
      * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
      * 
      * @param depts 閮ㄩ棬鍒楄〃
diff --git a/src/main/java/com/ruoyi/project/system/service/ISysMenuService.java b/src/main/java/com/ruoyi/project/system/service/ISysMenuService.java
index 432a280..4237f95 100644
--- a/src/main/java/com/ruoyi/project/system/service/ISysMenuService.java
+++ b/src/main/java/com/ruoyi/project/system/service/ISysMenuService.java
@@ -37,6 +37,14 @@
      * @return 鏉冮檺鍒楄〃
      */
     public Set<String> selectMenuPermsByUserId(Long userId);
+    
+    /**
+     * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+     * 
+     * @param roleId 瑙掕壊ID
+     * @return 鏉冮檺鍒楄〃
+     */
+    public Set<String> selectMenuPermsByRoleId(Long roleId);
 
     /**
      * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟鏍戜俊鎭�
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java
index 59d13a3..d189c4c 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java
@@ -47,6 +47,19 @@
     {
         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);
+    }
 
     /**
      * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
diff --git a/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java b/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
index 7946f97..7723315 100644
--- a/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
+++ b/src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java
@@ -101,6 +101,27 @@
     }
 
     /**
+     * 鏍规嵁瑙掕壊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鏌ヨ鑿滃崟
      * 
      * @param userId 鐢ㄦ埛鍚嶇О
diff --git a/src/main/resources/mybatis/system/SysMenuMapper.xml b/src/main/resources/mybatis/system/SysMenuMapper.xml
index aad73fd..5c4fca7 100644
--- a/src/main/resources/mybatis/system/SysMenuMapper.xml
+++ b/src/main/resources/mybatis/system/SysMenuMapper.xml
@@ -111,6 +111,13 @@
 		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}

--
Gitblit v1.9.3