01-权限系统总体设计-从身份资源到授权决策
权限系统总体设计:从身份、资源到授权决策
很多后台系统最初只有五张表:用户、角色、权限、用户角色、角色权限。它可以解决菜单和接口的基础访问控制,却很快会遇到无法自然表达的问题:某份合同只分享给三个人、销售只能看自己负责的客户、财务主管审批额度为十万元、管理员不能审批自己创建的付款单、外部成员只能临时访问项目文档、AI Agent 代表用户执行时不能突破自身工具权限。
这些问题说明,权限系统不是“把权限字符串装进用户对象”,而是一套围绕身份、资源、关系、属性、作用域和生命周期建立的决策体系。
1. 认证、授权、审计和业务校验
四者必须分开:
| 层次 | 回答的问题 | 典型实现 |
|---|---|---|
| 认证 Authentication | 请求方是谁 | Session、JWT、OIDC、证书、Workload Identity |
| 授权 Authorization | 能否执行这个操作 | RBAC、ACL、ABAC、ReBAC、数据权限 |
| 审计 Audit | 谁在何时做了什么 | 决策日志、授权变更日志、业务操作日志 |
| 业务校验 | 当前业务状态是否允许执行 | 状态机、额度、库存、审批流、乐观锁 |
JWT 不是权限模型,OAuth 2.0 也不是企业角色系统。Token 可以携带身份或部分授权信息,但最终仍要由资源服务判断请求是否被允许。
以付款单 P1001 为例:王芳通过认证后证明自己是 U1003;权限系统判断她是否拥有 finance:payment:approve、是否在华东分公司的作用域内、是否超过审批额度;业务系统再判断付款单是否处于 PENDING_APPROVAL、是否已经被其他流程处理。任何一层失败,操作都不能执行。
2. 一次权限判断有哪些对象
简化模型是:
Subject + Resource + Action + Context → Decision
企业系统需要更完整地记录:
Actor + Principal + Subject + Resource + Action + Context + Scope
→ Decision + Reason + Obligations
Actor、Principal、Subject
普通操作中三者通常相同:张三登录后读取自己的订单,实际操作者、已认证身份和被评估主体都是张三。
代理场景中则不同。赵强模拟张三排查问题时:
Actor = 赵强
Principal = 赵强
Subject = 张三
系统按照张三的权限返回页面,但审计日志必须记录真正操作者赵强。AI Agent 代表用户执行时也必须同时记录 Agent 和用户,不能只留下用户身份。
Resource 与 Action
Resource 是被保护对象,可以是资源类型,也可以是具体实例:
资源类型:order、payment、document
资源实例:O1001、P1001、D1001
Action 应使用业务语义:
read、update、approve、reject、export、share、assign
approve 不能被模糊地塞进 update,导出也不应从读取权限自动推导,因为它们具有不同风险和审计要求。
Context 与 Scope
Context 是请求时的动态环境,例如时间、IP、设备可信度、风险评分和 MFA 状态。Scope 是授权在哪个边界内有效,例如华东销售部、Project-A、当前租户或某份文档。
权限与作用域应成对保存:
sales:order:read → 华东销售部
sales:order:export → Project-A
不能先把权限合并成字符串集合,再把所有 Scope 混成一个大范围。
3. 人类和非人权限主体
权限主体不只有员工。
人类主体
- 正式员工:通常由 HR 和组织系统驱动生命周期。
- 管理员:具有管理能力,但不应天然拥有所有业务数据。
- 外部用户:需要明确的赞助人、有效期和资源范围。
- 临时人员:权限必须自动过期,不能依赖人工记忆回收。
非人主体
- 服务账号:有负责人、凭证轮换和到期时间。
- 微服务:使用服务身份访问下游,不能伪装成任意用户。
- 定时任务:需要限制时间窗口、数据范围和批量操作能力。
- 第三方应用:通过 OAuth Scope 或应用角色获得最小权限。
- AI Agent:既要受用户权限限制,也要受 Agent 自身工具权限限制。
统一抽象 Principal 有利于复用 Role Assignment、ACL 和审计机制,但不同类型的凭证和治理策略不能完全相同。
4. 权限粒度
企业系统常见粒度包括:
- 菜单、页面和按钮:主要服务前端体验。
- API 与业务操作:真正的后端安全边界。
- 数据行:决定可以访问哪些订单、客户和付款单。
- 字段:决定敏感字段隐藏、脱敏、只读或禁止导出。
- 资源实例:控制某份文档、某个项目和某张报表。
- 动态条件:根据金额、时间、设备、风险和业务关系判断。
前端隐藏按钮不能替代后端鉴权。攻击者不需要点击按钮,可以直接构造 HTTP、RPC 或消息请求。
5. ACL、RBAC、ABAC 与 ReBAC
ACL:从资源出发
D1001 的 ACL 可以记录:Project-A 项目组允许读取,Alice 允许评论但禁止下载。它适合具体资源分享和资源树继承。
RBAC:从职责出发
王芳获得财务主管角色,角色包含付款读取、审批、拒绝和导出权限。RBAC 擅长规模化管理稳定的功能权限。
ABAC:从属性和上下文出发
即便拥有审批权限,王芳只有在金额不超过审批额度、不是本人创建、MFA 有效且设备风险可接受时才能批准。ABAC 处理动态条件。
ReBAC:从关系图出发
张三是 Project-A 的成员,D1001 属于 Project-A,因此张三可以读取 D1001。ReBAC 适合项目、团队、负责人和资源包含关系。
这些模型不是互相取代。成熟系统通常用 RBAC 提供基础能力,用 ACL/ReBAC 精确到资源,用 ABAC 添加动态限制,再由数据权限把结果落实到数据库访问。
6. 功能权限、数据权限和业务规则
三者经常被混在一起:
功能权限:张三能否查询订单?
数据权限:张三能查询哪些订单?
业务规则:当前订单是否允许修改?
SALES_MANAGER_EAST_CHINA 这种角色把职位、地区和数据范围绑在一起,短期方便,长期会造成角色爆炸。更稳妥的设计是:
Role = SALES_MANAGER
Permission = sales:order:read
Scope = ORG-110
Data Scope = DEPARTMENT
7. 权限从哪里来
用户最终权限可能来自:
- 直接 Role Assignment;
- 用户组、组织和岗位的间接角色;
- 角色层级继承;
- ACL 和资源所有权;
- 项目成员等业务关系;
- 临时委托;
- ABAC 策略;
- 系统默认权限。
系统不能只保存“最终有权限”这一结果,还要保留来源链。否则当用户退出项目组或临时授权到期时,无法准确撤销对应来源,也无法解释为什么用户仍有同一权限。
8. 传播和冲突不是一套规则
不同模型的传播机制不同:
- ACL:父资源向子资源继承,可选择停止继承。
- RBAC:高级角色继承基础角色的权限,但不自动扩大 Scope。
- ABAC:组织、资源分类或默认属性向下传播,由策略优先级处理冲突。
- 数据权限:上级组织范围可以包含下级,但下级不会反向获得上级数据。
- ReBAC:只沿预先声明的关系路径推导,不能无限遍历任意关系。
统一原则只有两个:默认拒绝;租户隔离和系统级强制规则优先。ACL 是否 Deny 优先、ABAC 使用哪种组合算法,应由具体模型显式定义。
9. 权限系统的组件边界
一个完整系统通常包含:
- 身份系统:认证、Token、凭证和 MFA。
- 组织中心:员工、部门、岗位和汇报关系。
- 权限目录:应用、资源类型、操作和权限元数据。
- 授权管理:角色、ACL、Scope、委托和有效期。
- PAP:管理和发布策略。
- PDP:计算允许或拒绝。
- PIP:提供组织、资源、设备和风险属性。
- PEP:在 API、Service、Repository 或网关执行决策。
- 审计中心:记录授权变更、决策和业务操作。
权限中心不应复制全部订单、客户和付款单数据。业务状态和动态资源属性仍由业务系统负责,权限中心通过请求上下文或 PIP 获取决策所需的最小信息。
10. 一次请求的默认决策顺序
- 验证 Principal、凭证、会话和主体状态。
- 建立 Actor、Subject、Tenant、Resource、Action、Context。
- 检查租户边界、禁用状态、撤销和强制安全策略。
- 收集角色、ACL、关系、委托和所有权来源。
- 判断基础功能权限。
- 计算 Scope、数据范围和字段限制。
- 执行 ABAC、职责分离和风险策略。
- 返回
ALLOW或DENY,并携带原因和 Obligations。 - 业务系统执行脱敏、水印、MFA 和审计义务。
- 继续执行状态机、乐观锁和业务事务。
没有任何明确 Allow、必需属性缺失、权限服务无法确定结果时,都应拒绝。低风险操作是否允许使用有效本地快照降级,需要显式配置;高风险审批和权限管理通常应在无法验证最新版本时拒绝。
11. 权限编码
专题统一采用:
<domain>:<resource>:<action>
例如:
sales:order:read
finance:payment:approve
document:file:download
iam:role:assign
编码不包含 tenant_id、organization_id、用户 ID 和资源实例 ID。具体边界由 Scope、Data Scope、ACL 和 Policy 表达。权限进入生产后不能静默改变语义;破坏性变化应创建新权限并执行迁移。
12. 小结
权限系统的核心不是角色表,而是建立可追踪的授权关系,并在一次请求中把身份、资源、操作、作用域、关系和动态条件组合成可解释决策。
后续文章将分别展开:ACL 如何管理资源实例,RBAC 如何管理角色和约束,ABAC 如何建立策略引擎,数据权限如何进入 SQL,企业如何治理权限生命周期,以及权限中心如何处理缓存、一致性和测试。
参考资料
01-权限系统总体设计-从身份资源到授权决策
https://lautung.com/archives/RlLGAUES
评论