Skip to content

数据权限规则

Forge 通过 DataScopeInterceptor 实现行级数据权限控制。你需要理解它与 @SaCheckPermission 的区别,以及 Mapper XML 的正确写法。

数据权限 vs 功能权限

维度功能权限数据权限
注解@SaCheckPermissionDataScopeInterceptor
控制粒度接口能否访问能看到哪些数据行
作用层ControllerMapper SQL 改写
场景用户有没有"删除"按钮用户只能看本部门数据
java
// 功能权限:控制接口能否访问
@SaCheckPermission("system:user:list")
@GetMapping("/page")
public RespInfo page() { ... }

// 数据权限:控制返回哪些行(DataScopeInterceptor 自动改写 SQL)
// 无需注解,拦截器按 mapperMethod 匹配自动改写

DataScopeInterceptor 工作原理

拦截器按 mapperMethod(Mapper 接口全限定名 + 方法名)精确匹配,找到匹配规则后改写 SQL:

sql
-- 原始 SQL
SELECT u.* FROM sys_user u WHERE u.del_flag = 0

-- 改写后(根据当前用户的数据权限范围)
SELECT u.* FROM sys_user u
WHERE u.del_flag = 0
  AND (u.create_dept IN (SELECT dept_id FROM sys_dept WHERE FIND_IN_SET(dept_id, #{dataScope})))

数据权限范围取决于用户角色的 data_scope 配置:

data_scope 值含义SQL 效果
1全部数据不追加条件
2自定义数据dept_id IN (配置的部门)
3本部门数据dept_id = 当前部门
4本部门及以下dept_id IN (本部门 + 下级)
5仅本人create_by = 当前用户

Mapper XML 写法

需要数据权限的查询必须写在 XML 中,因为拦截器按 mapperMethod 精确匹配:

xml
<!-- 正确:写在 XML 中,拦截器能匹配到 -->
<select id="selectUserPage" resultType="SysUserVO">
    SELECT u.id, u.username, u.nickname, u.create_dept
    FROM sys_user u
    WHERE u.del_flag = 0
    ORDER BY u.create_time DESC
</select>

<!-- 禁止:在 Service 层用 LambdaQueryWrapper,拦截器无法匹配 -->
lambdaQuery().eq(SysUserEntity::getStatus, "0").list();

配置数据权限

  1. sys_role 表设置角色的 data_scope
  2. data_scope = 2(自定义)时,在 sys_role_dept 配置可访问的部门
  3. Mapper 方法名需要在 DataScopeInterceptor 中注册

关键约束

  • SQL 必须写在 Mapper XML 中DataScopeInterceptormapperMethod 匹配改写
  • 查询 SQL 必须包含 create_dept 字段,拦截器基于此字段过滤
  • 仅单表 selectByIdinsertupdateByIddeleteById 等内置方法允许用 MyBatis-Plus API
  • 数据权限与租户隔离可以叠加,两者互不影响

Forge Admin — 基于 Vue3 + Spring Boot 的企业级后台管理框架