目录
2.3 handleDataScope(point, controllerDataScope);分析
2.4.4 DATA_SCOPE_DEPT_AND_CHILD
一、从前端感受数据权限
1. 查看管理员分配

从超级管理员用户管理页面可以看到,可以给每一个用户分配数据权限。
2. 查看权限分类

在数据分配权限中可以发现,权限范围分成了五种类型,分别是全部数据,自定义主句,本部门数据,本部门数据及以下数据和仅本人数据权限。从名字中不难看得出来在自定义数据权限中可以自己分哪些部门的数据权限的可见是数据。
3. 进去用户界面感受差别

发现用户界面就只有他自己的数据
4. 使用管理员修改查看api调用

通过前端的api调用我们可以看到,他往后端调用了dataScope。
二、 从后端分析解析实现
1. 后端全文件搜索dataScope

从这里我们会发现他使用到了@DataScope + AOP的方法
2. 解析DataScopeAspect.java

从这里可以发现@annotation(controllerDataScope) 是切入点表达式,表示匹配被 @DataScope 注解标记的方法@DataScope 注解标记时,会在方法执行前调用 doBefore 方法,那么问你就找一下标记的地方在哪里
2.1 service层方法被标记@DataScope

从这里我们可以知道数据是这service这边进行的修改
2.2 clearDataScope(point);解析

从这里我们发现他先进行了一步将数据进行清空,并进行了判定如果不是空值的他会存放一个空的键值对进行替换。
2.3 handleDataScope(point, controllerDataScope);分析

从这里我们可以知道它主要是获取当前登录的用户信息,当用户不是超级管理员时进行执行dataScopeFilter()
2.4 dataScopeFilter()解析
这里我们发现他刚刚好对应上了之前修改表的几个类型

2.4.1 DATA_SCOPE_ALL

2.4.2 DATA_SCOPE_CUSTOM

添加一段sql语句,role.getRoleId(): 获取当前角色的ID
查找部门ID在sys_role_dept表中与当前角色关联的部门
sys_role_dept表存储了角色和部门的多对多关系
这样就能查询出当前角色被授权访问的所有部门数据
2.4.3 DATA_SCOPE_DEPT

添加一段sql语句 user.getDeptId(): 获取当前用户所属的部门ID
2.4.4 DATA_SCOPE_DEPT_AND_CHILD
添加一段sql语句 user.getDeptId(): 获取当前用户所属的部门ID
dept_id = user.getDeptId(): 匹配当前用户所在部门
find_in_set(user.getDeptId(), ancestors): 匹配祖先部门列表中包含当前部门ID的记录
ancestors 是 sys_dept 表中的字段,存储了部门的祖先部门ID列表
2.4.5 DATA_SCOPE_SELF

StringUtils.isNotBlank(userAlias):检查是否提供了用户表别名
有用户别名时:
sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())):构建SQL条件,限制只能查询当前用户ID的数据
无用户别名时:
sqlString.append(" OR 1=0 "):添加永假条件,确保不返回任何数据
这是因为没有用户别名就无法构建正确的用户ID过滤条件,为安全起见直接返回空结果
2.3.6 最后构建好的SQL权限条件注入到查询参数中

StringUtils.isNotBlank(sqlString.toString()):检查是否构建了有效的SQL条件字符串
Object params = joinPoint.getArgs()[0]:获取目标方法的第一个参数
params instanceof BaseEntity:确保参数是 BaseEntity 类型,因为只有该类型的对象才有(因为BaseEntity是父类进行存储这样子可以更好的通用)
sqlString.substring(4):去除开头的" OR "字符串,因为SQL条件是从"OR"开始构建的
baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"):将构建好的SQL条件以 AND 的形式存储到 BaseEntity 的 params 中,键名为 dataScope
2.4 总结
后端总流程
通过 @DataScope 注解 + AOP 切面,在 Service 层方法执行前清空残留权限数据,为非超级管理员用户按全部权限、自定义部门、所属部门、部门及子部门、仅本人 5 种权限类型构建 SQL 过滤条件,最终将条件注入通用父类 BaseEntity 的参数中,实现通用的数据权限控制。(如果不使用BaseEntity 继承的话,会导致不通用)
三、新数据库进行数据权限
1. 新建数据库


105测试部门 106财务部门
2. 使用ruoyi代码生成

3. 进行用户新增和权限分配


4. 后端添加 @DataScope


4. 登录不同用户查看效果
超级管理员用户

ry普通用户(测试部门)

cyq普通用户(财务部门)


2万+

被折叠的 条评论
为什么被折叠?



