数据权限控制
# 数据权限控制
在企业级应用中,数据权限控制是一项重要的功能,用于确保用户只能访问与其角色和部门权限相符的数据。若依框架提供了一套完整的数据权限控制机制,通过注解和拦截器结合 MyBatis 实现了灵活的权限管理。本文将详细介绍若依框架中数据权限的实现方法,包括注解的使用、数据权限的配置和 SQL 查询的过滤逻辑。
# 一、数据权限注解 @DataScope
参数说明
若依框架提供的 @DataScope
注解用于标注需要进行数据权限控制的业务方法。通过配置注解参数,可以指定部门表和用户表的别名,从而实现基于部门和用户的数据权限过滤。
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
deptAlias | String | 空 | 部门表的别名,用于SQL查询过滤 |
userAlias | String | 空 | 用户表的别名,用于SQL查询过滤 |
# 1. deptAlias
参数
deptAlias
参数用于指定部门表的别名。当业务 SQL 查询中涉及部门数据权限过滤时,需要为部门表设置别名,并在 @DataScope
注解中使用该别名。
@DataScope(deptAlias = "d")
public List<User> selectUserList(User user)
{
return userMapper.selectUserList(user);
}
2
3
4
5
# 2. userAlias
参数
userAlias
参数用于指定用户表的别名。当业务 SQL 查询中需要同时过滤用户和部门数据权限时,使用 userAlias
参数设置用户表的别名。
@DataScope(deptAlias = "d", userAlias = "u")
public List<User> selectUserList(User user)
{
return userMapper.selectUserList(user);
}
2
3
4
5
# 二、数据权限的配置和使用
在若依框架中,数据权限主要通过角色配置来实现。管理员可以在角色管理中为角色配置数据权限范围,并通过 @DataScope
注解结合 MyBatis SQL 查询,实现对数据的权限控制。
# 1. 配置数据权限
在“系统管理 - 角色管理”中,可以为角色配置数据权限。若依框架支持以下几种数据权限配置:
- 全部数据权限:角色可以访问系统中的所有数据。
- 自定义数据权限:角色可以访问管理员指定的数据范围。
- 部门数据权限:角色只能访问自己所在部门的数据。
- 部门及以下数据权限:角色可以访问自己所在部门及其下属部门的数据。
- 仅本人数据权限:角色只能访问自己创建的数据。
# 2. 数据权限控制的使用
在业务方法上使用 @DataScope
注解,通过设置 deptAlias
和 userAlias
参数来实现数据权限的控制。
- 部门数据权限注解:
@DataScope(deptAlias = "d")
public List<User> selectUserList(User user)
{
return userMapper.selectUserList(user);
}
2
3
4
5
- 部门及用户数据权限注解:
@DataScope(deptAlias = "d", userAlias = "u")
public List<User> selectUserList(User user)
{
return userMapper.selectUserList(user);
}
2
3
4
5
# 三、SQL 查询中的数据权限过滤
在使用 @DataScope
注解的方法中,MyBatis 会自动在 SQL 查询中添加数据权限的过滤条件。开发者只需在 MyBatis 的 XML 配置中使用 ${params.dataScope}
即可实现自动的权限过滤。
# 1. 未过滤数据权限的 SQL 查询示例
以下是用户管理中,未进行数据权限过滤的 SQL 查询示例:
select u.user_id, u.dept_id, u.login_name, u.user_name, u.email,
u.phonenumber, u.password, u.sex, u.avatar, u.salt,
u.status, u.del_flag, u.login_ip, u.login_date, u.create_by,
u.create_time, u.remark, d.dept_name
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
where u.del_flag = '0'
2
3
4
5
6
7
# 2. 已过滤数据权限的 SQL 查询示例
在进行数据权限过滤后,SQL 查询会自动添加相应的条件:
select u.user_id, u.dept_id, u.login_name, u.user_name, u.email,
u.phonenumber, u.password, u.sex, u.avatar, u.salt,
u.status, u.del_flag, u.login_ip, u.login_date, u.create_by,
u.create_time, u.remark, d.dept_name
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
where u.del_flag = '0'
and u.dept_id in (
select dept_id
from sys_role_dept
where role_id = #{roleId}
)
2
3
4
5
6
7
8
9
10
11
12
通过角色部门表(sys_role_dept
)完成数据权限过滤。
# 3. 在 MyBatis 查询中添加数据范围过滤
在 MyBatis 的 XML 配置文件中,使用 ${params.dataScope}
来插入数据权限过滤条件。
<select id="selectUserList" parameterType="com.ruoyi.system.domain.User" resultMap="BaseResultMap">
select u.user_id, u.dept_id, u.login_name, u.user_name, u.email,
u.phonenumber, u.password, u.sex, u.avatar, u.salt,
u.status, u.del_flag, u.login_ip, u.login_date, u.create_by,
u.create_time, u.remark, d.dept_name
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
where u.del_flag = '0'
${params.dataScope}
</select>
2
3
4
5
6
7
8
9
10
# 四、数据权限的逻辑实现
数据权限的核心逻辑是通过 AOP 切面和 MyBatis 拦截器来实现的。在若依框架中,DataScopeAspect
切面类负责拦截标记了 @DataScope
注解的方法,并动态生成数据权限的 SQL 片段,注入到查询中。
# 1. DataScopeAspect
切面类
DataScopeAspect
切面类通过拦截标注了 @DataScope
注解的方法,解析注解参数,并将生成的数据权限 SQL 片段注入到 MyBatis 查询参数中。
package com.ruoyi.framework.aspectj;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.util.Map;
@Aspect
@Component
public class DataScopeAspect
{
@Before("@annotation(dataScope)")
public void doBefore(JoinPoint point, DataScope dataScope)
{
// 获取方法参数
Object params = point.getArgs()[0];
if (params != null && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
Map<String, Object> dataScopeMap = baseEntity.getParams();
if (StringUtils.isNotEmpty(dataScope.deptAlias()))
{
dataScopeMap.put("dataScope", getDeptDataScope(dataScope.deptAlias()));
}
if (StringUtils.isNotEmpty(dataScope.userAlias()))
{
dataScopeMap.put("dataScope", getUserDataScope(dataScope.userAlias()));
}
}
}
// 部门数据权限过滤逻辑
private String getDeptDataScope(String deptAlias)
{
// 根据角色获取部门数据权限
// 示例:and d.dept_id in (select dept_id from sys_role_dept where role_id = ?)
return StringUtils.format(
"and {}.dept_id in (select dept_id from sys_role_dept where role_id = ?)", deptAlias);
}
// 用户数据权限过滤逻辑
private String getUserDataScope(String userAlias)
{
// 根据用户获取数据权限
// 示例:and u.user_id in (select user_id from sys_role_user where role_id = ?)
return StringUtils.format(
"and {}.user_id in (select user_id from sys_role_user where role_id = ?)", userAlias);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 2. 通过 BaseEntity 实现数据权限控制
数据权限 SQL 片段会存储到 BaseEntity
对象中的 params
属性中,并通过 ${params.dataScope}
在 MyBatis XML 文件中进行动态拼接,实现数据权限控制。
public class BaseEntity
{
private Map<String, Object> params;
public Map<String, Object> getParams()
{
return params;
}
public void setParams(Map<String, Object> params)
{
this.params = params;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 五、总结
通过 @DataScope
注解结合 MyBatis 拦截器,若依框架实现了灵活且强大的数据权限控制机制,确保不同角色的用户只能访问符合其权限的数据。
- 数据权限配置: 在角色管理中配置不同的数据权限范围,支持多种权限模式,如全部数据、自定义数据、部门数据、仅本人数据等。
- 注解使用简便: 通过
@DataScope
注解,轻松实现数据权限控制,无需手动编写复杂的 SQL 查询。 - SQL 查询过滤: 数据权限过滤条件会自动拼接到 SQL 查询中,确保查询结果符合数据权限的要求。
- 灵活扩展: 可以根据实际业务需求,自定义数据权限的过滤逻辑和 SQL 拼接方式,满足不同场景的需求。