企业级数据权限方案 · 决策与执行解耦 · 不依赖数据库的行级/列级权限体系

企业级数据权限方案 · 决策与执行解耦 · 不依赖数据库的行级/列级权限体系

版本 v1.0 · 2026-08-24
定位:一份可落地到 cmx-* 生态的**数据权限(Data Authorization)**完整设计。核心主张——把"谁能看什么"(决策)与"在哪里过滤"(执行)彻底解耦,让权限策略写一次、DB 无关、多点执行、可单测。


目录

  1. 问题重述:数据权限真的必须依赖数据库吗?
  2. 执行点谱系:三档方案的取舍
  3. 核心范式:PDP/PEP 分离 + 部分求值(残差约束)
  4. 总体架构:一芯多壳 + 约束 AST 为轴
  5. 领域模型:Subject / Resource / Decision / Constraint
  6. 约束 AST:四种权限范型的公共表示
  7. 数据库表结构设计
  8. 请求链路时序
  9. 维度权限 ⊕ 关系权限(ReBAC)
  10. 列脱敏(Column Masking)
  11. 缓存策略
  12. 与 cmx-* 生态的集成
  13. 核心接口(Rust)
  14. 防绕过与安全纵深
  15. 落地路线图 D0–D6
  16. FAQ 与常见误区

一、问题重述

你的原始判断是:

传统 ERP 数据权限,最终无非返回一段 SQL 拼进 WHERE,过滤数据,依赖数据库

这句话把两件本应分开的事情绑死在了一起:

关注点 本质问题 传统做法 是否必须在 DB?
决策(Decision) 谁、对什么资源、能做什么 埋在 SQL 片段/存储过程里
执行(Enforcement) 过滤实际发生在哪一层 拼进 WHERE,DB 执行 视场景而定

fig-decision-vs-enforce

一旦把"决策"从"执行"里剥出来,"不依赖数据库"的空间就打开了:决策可以完全在应用层(策略引擎)完成,执行则退化成一个可替换的后端——SQL 只是其中一种,不是唯一。

一句话结论:传统方案依赖的不是"数据库"这个东西,而是"过滤逻辑与数据同库、且能表达成 SQL"这个耦合。打破耦合的钥匙,是一个语义中立的约束中间表示(约束 AST)


二、执行点谱系

"数据在哪里被过滤"决定了你有多依赖数据库。存在三档,构成一条连续谱系:

fig-spectrum

档位 决策位置 执行位置 DB 依赖 可分页/聚合 规则复杂度上限
① DB 原生 RLS DB(策略函数) DB 引擎 极高 中(受 SQL 表达力限制)
② 查询改写下推 应用层 DB(拼 WHERE) 中(可移植)
③ 拉取后过滤 应用层 应用内存 任意

三档没有绝对优劣,正确的系统会同时用到 ②③,并让 ① 作为高敏兜底。关键洞察在于:

  • ①(RLS) 是唯一真正"依赖数据库"的方案——逻辑写在 CREATE POLICY / PL/pgSQL 里,锁死 DB 品牌,难以单测,跨服务无力。它的不可替代优点是防绕过:任何直连 DB 的查询都逃不掉。
  • ②(查询改写) 才是绝大多数 ERP(若依 @DataScope、Hibernate @Filter、MyBatis 拦截器)的真身。它的决策逻辑其实在应用层,DB 只是被动执行 SQL。它依赖的不是"数据库",而是"能下推"。
  • ③(拉取后过滤) 彻底不碰 DB 逻辑,规则任意复杂,但无法正确分页/count/聚合,只适合单对象或小结果集(详情页、单据校验)。

②③ 的分野,正是经典的 PDP / PEP 分离:决策点(Policy Decision Point)和执行点(Policy Enforcement Point)本就不必是同一个地方。


三、核心范式

3.1 PDP / PEP 分离

借鉴 XACML 的经典分层,把系统拆成两个角色:

  • PDP(决策点):输入主体上下文与资源描述,输出"允许/拒绝 + 约束条件"。与任何数据库无关,纯逻辑,可 wasm、可单测。
  • PEP(执行点):拿到 PDP 的决策,负责在具体数据源上执行过滤。SQL 下推、内存谓词、ES 查询,都是 PEP 的不同实现。

3.2 部分求值(Partial Evaluation)—— 本方案的灵魂

朴素的 PDP 只能回答"是/否"(permit(user, action, one_row) → bool),这正是档位③的困境:必须逐行拉取再判定。

突破口:让 PDP 做部分求值——把策略里"已知的上下文"(当前用户、角色、组织维度)代入求值,把"尚未知晓的资源字段"(ownerstatusdept_id保留为符号,最终吐出一棵只剩资源约束的残差谓词树

fig-pdp-pep

策略:  可见 ⟺ dept_id ∈ 我的部门集 ∧ (owner = 我 ∨ status = 'public')
              └── 已知(代入)──┘   └────── 未知(保留)──────┘

部分求值后的残差:
        dept_id IN [1001, 1002] AND (owner = 'u42' OR status = 'public')

这棵残差树就是约束 AST。它:

  • 与 DB 无关——是一棵纯数据结构,可序列化成 JSON;
  • 可被任意后端编译——SQL 编译器把它变成 WHERE,内存编译器把它变成 Fn(&Row) -> bool,ES 编译器把它变成 bool query
  • 一次决策,多处执行——同一棵 AST 可下推到 PG、内存过滤 CSV、查询 ES。

这就是"不依赖数据库"的精确含义:你依赖的是策略引擎,而 DB 只是众多编译目标之一。学术与工业界的同类实现:OPA 的 Compile/Partial Eval API、Oso 的 Data Filtering、AWS Cedar 的 partial evaluation。


四、总体架构

沿用你在 cmx-flowengine / cmx-rulesengine 上验证过的"一芯多壳"哲学:一个语义中立的内核 cmx-dataauth-core,外面包裹可插拔的策略源与执行后端。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值