授权模型
授权决定已验证身份的用户(或匿名用户)可以做什么。数据墙DBW 使用基于角色的访问控制(RBAC)模型,从实体级别的操作控制到行级别的数据过滤,构成了完整的授权体系。
RBAC 核心概念
text
请求 → 确定角色 → 查找权限 → 评估策略 → 执行操作数据墙DBW 的授权围绕四个核心概念展开:
| 概念 | 说明 | 配置位置 |
|---|---|---|
| 角色 | 用户的分类标识,分为系统角色和用户角色 | 身份验证令牌或 X-MS-API-ROLE 头 |
| 权限 | 角色在特定实体上被允许执行的操作 | entities.{name}.permissions |
| 策略 | 行级别的数据过滤表达式 | permissions.actions.policy.database |
| 字段控制 | 按角色限制可访问的字段 | permissions.actions.fields |
多层授权架构
授权在三个层级上独立配置,层层递进:
text
第一层:实体级授权
└── 这个角色能访问这个实体吗?能执行哪些操作(read/create/update/delete/execute)?
第二层:字段级控制
└── 这个角色在这个操作中能访问哪些字段?哪些字段被排除?
第三层:行级过滤
└── 这个角色能看到哪些数据行?通过什么条件过滤?引擎按顺序评估:先检查实体操作权限 → 再应用字段过滤 → 最后追加行级策略。任何一层不满足,请求被拒绝。
请求评估流程
当请求到达数据墙DBW 时,引擎执行以下授权评估:
text
1. 确定最终生效角色(来自身份验证层)
↓
2. 查找该角色在目标实体上是否有显式配置的权限块
├── 有 → 进入步骤 3
└── 没有 → 沿继承链查找(named-role → authenticated → anonymous)
├── 找到 → 进入步骤 3
└── 没有 → 返回 403 Forbidden
↓
3. 检查该角色的权限块是否包含请求的操作
├── 包含 → 进入步骤 4
└── 不包含 → 返回 403 Forbidden
↓
4. 应用字段级过滤(include / exclude)
↓
5. 将行级策略表达式转换为数据库查询谓词
├── 解析 @claims 引用
└── 生成 WHERE 条件
↓
6. 执行数据库查询 / 操作系统角色 vs 用户角色
| 维度 | 系统角色 | 用户角色 |
|---|---|---|
| 角色名 | Anonymous、Authenticated | 自定义(如 editor、admin) |
| 来源 | 引擎根据请求自动分配 | JWT 令牌的 roles 声明 |
| 配置要求 | 默认可用 | 需在身份提供程序中配置输出 |
| 选择方式 | 不携带 X-MS-API-ROLE 时自动选择 | 请求中携带 X-MS-API-ROLE 头 |
| 大小写 | 不区分(ANONYMOUS = anonymous) | 区分大小写,须与配置完全一致 |
单一角色评估原则
每次请求只在一个最终生效角色的上下文中评估。即使 JWT 令牌中包含多个角色,引擎也只会使用一个角色来判断权限。角色选择规则:
| 请求状态 | 最终角色 |
|---|---|
| 无认证信息 | Anonymous |
| 已认证但未指定角色 | Authenticated |
| 已认证且指定了角色(令牌中包含该角色) | 指定角色 |
| 已认证但指定了不存在的角色 | 请求被拒绝(403) |
角色继承不会将多个角色的权限合并——继承是"如果自身没有配置,则用更宽泛角色的配置",而不是"同时拥有自身和更宽泛角色的全部权限"。
权限操作类型
每个操作对应数据库层面的具体行为:
| 操作 | 配置值 | 适用对象 | 数据库行为 |
|---|---|---|---|
| 查询 | read | 表、视图 | SELECT |
| 创建 | create | 表、视图 | INSERT |
| 更新 | update | 表、视图 | UPDATE |
| 删除 | delete | 表、视图 | DELETE |
| 执行 | execute | 存储过程 | EXEC |
| 全部 | * | 表、视图 | CREATE+READ+UPDATE+DELETE |
| 全部 | * | 存储过程 | EXECUTE |
* 通配符根据实体类型自动扩展为对应操作集,避免意外授予不兼容的操作权限。
默认安全原则
数据墙DBW 从设计上遵循"默认拒绝"原则:
- 未配置
permissions的实体默认没有权限,所有请求返回 403。 - 未在配置文件中引用的数据库对象不会暴露在 API 中。
- JWT 令牌中引用的声明不存在时,策略对应的请求返回 403。
这种设计确保安全是显式配置的结果,而不是默认开放。
