2. RICE 角色模型拆解:四个核心维度的精确含义
多租户权限设计中最致命的错误,是将“角色”当作唯一维度直接绑定菜单。RICE 模型把权限拆解为四个独立但互锁的要素:Role(角色)、Identity(身份)、Capability(能力)、Entity(实体)。只有厘清每一层的职责,才能在跨租户、跨业务线、跨数据域的场景中实现精细而可扩展的授权。
2.1 四要素定义速览
| 要素 | 缩写 | 一句话定义 | 核心问题 |
|---|---|---|---|
| Role(角色) | R | 一组预定义的职责集合,通常与岗位对应 | 谁做什么? |
| Identity(身份) | I | 用户在系统中的唯一标识及其上下文属性 | 你是谁?属于哪个租户? |
| Capability(能力) | C | 可执行的操作原子,如“创建订单”“删除报表” | 能做什么操作? |
| Entity(实体) | E | 操作作用的对象,如“客户A的订单”“部门B的预算” | 对什么资源做? |
📌 记忆口诀:“角色定岗,身份定户,能力定权,实体定数。” —— 四者组合才构成一条完整的授权规则。
2.2 逐层深度拆解
▸ Role(角色)—— 职责的容器
角色是将多个Capability打包的逻辑组。典型的角色如“销售经理”“财务审核员”。角色本身不包含数据范围,只说明“这个人应该拥有哪些操作权限”。在多租户环境下,角色模板可以跨租户共享,但各租户可修改其绑定的能力集。
▸ Identity(身份)—— 租户与用户的双重锚
Identity = 用户全局标识 + 租户归属 + 额外属性(部门、职级、区域)。同一个用户在不同租户下拥有不同的身份。身份决定了默认的角色指派以及数据隔离边界。
▸ Capability(能力)—— 不可再拆的原子操作
每个Capability对应一个REST API端点、一个页面按钮或一个后台服务调用。例如:order:create、report:export。能力不关心“谁在做”和“对哪条数据做”,只描述动作本身。
▸ Entity(实体)—— 数据的范围与归属
实体是权限的“宾语”。常见实体类型:租户实例、客户、项目、合同、发票等。每个实体自带所属租户ID,因此通过Entity即可天然实现跨租户隔离。实体还支持层级(如“部门 → 小组 → 员工”)和条件(如“金额 < 1000 的订单”)。
2.3 四要素的协作关系
核心公式:一次权限判断 = 检查
User.Identity 是否拥有 Role,该 Role 包含所需 Capability,且该 Capability 的作用域覆盖目标 Entity。
2.4 类比:图书借阅系统
把权限系统比作图书馆管理:
- Role = 借阅员、图书管理员、馆长(岗位职责)
- Identity = 小明(员工编号A-123,所属分馆:朝阳分馆)
- Capability = 借书、还书、罚款、上架
- Entity = 哪本书、哪个书架、哪个读者的借阅记录
小明拥有“借阅员”角色,因此拥有“借书”能力,但只能操作“本分馆的图书实体”。换到另一分馆,Entity 范围变化,权限自动失效。
2.5 常见误区
⚠️ 误区1:把“角色”当作数据权限做控制。
后果:一个“销售经理”在A租户能看全部客户,在B租户却只能看自己跟进的客户,被迫创建“A租户销售经理”和“B租户销售经理”两个角色,角色爆炸。
正确做法:角色只管理操作集合,数据范围由Entity隔离。
后果:一个“销售经理”在A租户能看全部客户,在B租户却只能看自己跟进的客户,被迫创建“A租户销售经理”和“B租户销售经理”两个角色,角色爆炸。
正确做法:角色只管理操作集合,数据范围由Entity隔离。
⚠️ 误区2:混淆“身份”与“角色”。
后果:在代码中把用户ID直接映射为角色,导致跨租户共用身份时权限错乱。
正确做法:身份是上下文,角色是权限模板,永远通过“租户内的身份”去关联角色。
后果:在代码中把用户ID直接映射为角色,导致跨租户共用身份时权限错乱。
正确做法:身份是上下文,角色是权限模板,永远通过“租户内的身份”去关联角色。
⚠️ 误区3:Capability 粒度过粗或过细。
过粗(如一个“全部权限”能力)导致无法精细控制;过细(如每个按钮一个能力)导致角色配置工作量爆炸。
建议:一个 Capability 对应一个业务操作(如“提交审批”),而非一个HTTP方法。
过粗(如一个“全部权限”能力)导致无法精细控制;过细(如每个按钮一个能力)导致角色配置工作量爆炸。
建议:一个 Capability 对应一个业务操作(如“提交审批”),而非一个HTTP方法。
2.6 练习题
- 以下哪个属于 RICE 中的 Entity?
A. 财务审核员 B. 用户张三@租户A C. 删除发票 D. 合同编号 CON-20250301 - 小明在租户A拥有“管理员”角色,具备
user:create能力,但无法创建租户B的用户。这是因为 Entity 限制了什么? - 请用 RICE 四要素描述:李四(租户C财务部)可以导出自己部门的季度报表。
2.7 应用边界
| 场景 | 适用性 | 说明 |
|---|---|---|
| 单一租户小团队(<50人) | 🔴 过度设计 | RBAC + 数据软删除即可,不需要 Entity 层 |
| 多租户 SaaS(租户数>100) | 🟢 强烈推荐 | RICE 天然支持租户隔离与角色模板共享 |
| 内部企业门户(无多租户) | 🟡 可选 | 可降级为 RCE(Identity 弱化为部门) |
| 需要跨租户数据聚合的场景 | 🟢 必需 | Entity 层支持多实例范围查询 |