Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_EleVue/zh/core/data-scope.md
T
2026-10-08 17:50:29 +08:00

7.3 KiB
Raw Blame History

5.9 数据权限

:::tip 概述 数据权限控制用户能看到哪些数据,由 HasDataScope Trait 的 applyDataScope() 在查询构建时按角色数据范围自动叠加过滤条件,支持三种范围:全部数据、本部门数据、仅本人数据。当前 laravel_role 表不含 data_scope 字段——getRoleDataScope() 读取缺省为 1,所有角色按全部数据处理。 :::

三种范围

┌─────────────────────────────────────────────────────────┐
│                    data_scope = 1                        │
│                    全部数据(不过滤)                     │
│                                                         │
│  ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐                         │
│  │ A │ │ B │ │ C │ │ D │ │ E │  ← 所有部门所有人的数据  │
│  └───┘ └───┘ └───┘ └───┘ └───┘                         │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│                    data_scope = 2                        │
│                    本部门数据                            │
│                                                         │
│  ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐                         │
│  │ A │ │ B │ │███│ │ D │ │ E │  ← 只看到本部门数据      │
│  └───┘ └───┘ └───┘ └───┘ └───┘                         │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│                    data_scope = 3                        │
│             仅本人数据(无角色用户默认)                  │
│                                                         │
│  ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐                         │
│  │ A │ │ B │ │███│ │ D │ │ E │  ← 只看到自己创建的数据  │
│  └───┘ └───┘ └───┘ └───┘ └───┘                         │
└─────────────────────────────────────────────────────────┘

配置方式

:::warning 前置条件 数据权限能力由 HasDataScope Trait 提供——继承 BaseTenantService 的服务已自动 use 该 Trait;直接继承 BaseService 的服务需自行 use Concerns\HasDataScope。且 BaseTenantService 默认未启用数据权限,子类必须声明字段才会生效。 :::

class UserService extends BaseTenantService
{
    /**
     * 数据权限:部门关联字段名(用于按部门过滤,data_scope=2 时生效)
     *
     * @var string
     */
    protected string $dataScopeDeptField = 'dept_id';
}

class ArticleService extends BaseTenantService
{
    /**
     * 数据权限:归属字段名(用于按创建人过滤,data_scope=3 时生效)
     *
     * @var string
     */
    protected string $dataScopeUserField = 'create_user';
}
属性 生效场景 过滤条件
dataScopeDeptField data_scope=2 本部门 WHERE {字段} = 当前用户部门ID
dataScopeUserField data_scope=3 仅本人 WHERE {字段} = 当前用户名

实现机制

// app/Services/Concerns/HasDataScope.php(行为说明)

protected function applyDataScope($query)
{
    // 未配置数据权限字段则跳过
    if (empty($this->dataScopeUserField) && empty($this->dataScopeDeptField)) {
        return $query;
    }

    // 获取角色的数据权限范围
    $dataScope = $this->getRoleDataScope($roleId);

    // 1=全部数据,不做过滤
    if ($dataScope == 1) {
        return $query;
    }

    // 2=本部门数据(配置了 dataScopeDeptField 时)
    if ($dataScope == 2 && $this->dataScopeDeptField) {
        $deptId = $this->getUserDeptId($uid);
        if ($deptId) {
            $query = $query->where($this->dataScopeDeptField, $deptId);
        }
        return $query;
    }

    // 3=仅本人数据(配置了 dataScopeUserField 时)
    if ($dataScope == 3 && $this->dataScopeUserField) {
        return $query->where($this->dataScopeUserField, $username);
    }

    return $query;
}

查询链中的位置(HasQueryScopes::buildQuery):

额外固定条件($where)
    → LIKE 模糊匹配(pageLikeFields)
    → 精确匹配(pageEqFields)
    → 数据权限过滤(applyDataScope)      ← 本节
    → 租户隔离过滤(applyTenantScope)

:::warning 无角色用户 无角色时默认按"仅本人"(scope=3)处理——宁可少看,不可多看。 :::

数据范围语义

getRoleDataScope() 按以下范围解析(HasDataScope 内部实现):

值 范围 适用场景
1 全部数据 管理层、超级管理员(当前默认)
2 本部门数据 部门经理
3 仅本人数据 普通员工(无角色用户默认)

:::info 当前版本现状 laravel_role 表不包含 data_scope 字段(按当前表设计),角色一律解析为 1(全部数据);上表为 HasDataScope 的完整语义。服务只需声明 dataScopeUserField / dataScopeDeptField 字段,范围解析逻辑保持不变。 :::

超级管理员

uid=1 的超级管理员不受数据权限限制(权限与租户校验均跳过),始终看到全部数据。详见 5.4 权限管理(RBAC)。

与租户隔离的关系

数据权限和租户隔离是两个独立的维度:

  • 租户隔离:按 tenant_id 过滤,不同租户数据完全隔离(BaseTenantService 自动启用)
  • 数据权限:在同一租户内,按部门或创建人进一步过滤(需声明字段启用)

两者可以同时生效,租户隔离优先级更高(先租户、后数据权限)。详见 5.8 多租户隔离。

常见问题

现象 原因 处理
配置了字段但过滤不生效 服务未启用 HasDataScope 继承 BaseTenantService 或手动 use Trait
普通用户看到全部数据 当前角色数据范围解析为 1(表无 data_scope 字段) 属于当前版本现状,见上文「数据范围语义」
部门过滤失效(scope=2) 未配置 dataScopeDeptField 或用户无部门 声明字段并给用户分配部门
仅本人过滤失效(scope=3) 未配置 dataScopeUserField 声明字段(如 create_user)