2. RBAC 模型概述

做权限控制这么多年,我见过太多团队在接入 SDK 时把权限写死在代码里。用户 A 能点这个按钮,用户 B 不能,全靠 if-else 堆砌。结果呢?业务一扩展,改权限就得重新发版,出问题还得背锅。

后来我接触到了 RBAC(Role-Based Access Control,基于角色的访问控制)。说白了,就是把权限从用户身上抽离出来,交给“角色”这个中间层。你想想看,一家公司几百号人,每个人单独配权限,那是灾难。但如果你把权限先绑到“角色”上——比如“管理员”、“运营”、“普通用户”——再把人加到角色里,管理就清晰多了。

2.1 RBAC 的定义

RBAC 是一种权限管理思想。核心就一句话:用户不直接拥有权限,而是通过角色获得权限。

我记得在某个电商项目中,SDK 接入了十几个第三方服务。每个服务都有自己的一套权限模型。我们当时硬着头皮做了一个抽象层,把外部权限全部映射成内部角色。那段时间天天加班,但搞完后,所有服务的权限管理都统一了。这就是 RBAC 的力量。

核心要点: RBAC 不是一种具体的算法或框架,而是一种设计模式。你可以在任何语言、任何平台上实现它。

2.2 核心三要素

理解 RBAC,你只需要记住三个概念:用户(User)、角色(Role)、权限(Permission)。它们之间的关系可以用一张表说明:

要素 定义 我在项目中的理解
用户 系统里的主体,可以是人、服务账号、机器 其实就是“谁”在操作。我习惯把用户 ID 作为唯一标识。
角色 权限的集合,一种分类标签 角色就是把一堆权限打包。比如“运营”角色可以看订单、改商品,但不能改价格。
权限 对某个资源的操作许可,通常是“操作 + 资源”的组合 我常用 user:read 表示“读取用户信息”,order:write 表示“创建订单”。

2.3 它们怎么配合?

用户和角色是多对多关系。一个用户可以有多个角色,一个角色也可以属于多个用户。权限和角色也是多对多。这套模型,你能在大部分现代系统中看到身影。

举个真实例子。之前我改造一个旧 SDK,原来的权限判断长这样:

if (user.isAdmin || user.isOperator) {  
    // 允许编辑  
}  

写死不说,每次加新角色都得改这块代码。改成 RBAC 后:

if (user.hasRole("editor") || user.hasRole("admin")) {  
    // 允许编辑  
}  

角色逻辑集中管理,代码立马清爽了。

小提示: 权限字符串建议统一命名风格。我个人偏好 domain:action 格式,比如 report:export。这样在数据库里好检索,也方便写注解。

2.4 RBAC 的优势

为什么要学 RBAC?你想想看,如果没有角色层,每次新增用户你都得一个个配权限。如果有 100 个用户,你先给 50 个配置“编辑文章”,再给 30 个配置“删除评论”……光想都头大。

RBAC 的优势,我总结了四个核心点:

  1. 权限管理更灵活:改角色 = 改所有用户的权限。不用逐个用户调整。
  2. 安全性更高:权限最小化原则很容易落地。你给用户分配一个“只读”角色,他就别想写数据。
  3. 降低耦合:权限判断代码不再和用户身份绑定。角色变了,代码不用动。
  4. 审计更方便:谁有什么角色、角色有什么权限,查一下表就清楚了。

我曾经踩过一个坑:直接把权限写在用户表里。后来要增加一项权限,得写一个数据库迁移改所有用户记录。那感觉,嗯……后来我再也没这么干过。

注意: RBAC 虽然好,但别滥用。如果角色数量膨胀到上百个,管理成本反而变高。我建议角色控制在 10~20 个以内,过多时考虑引入角色分组或继承。

2.5 一张图看懂 RBAC 核心结构

下面这张图,能帮你快速建立 RBAC 的整体印象。每个关键节点我都标了颜色,方便你对照理解。

RBAC 核心结构图 用户(User) 角色(Role) 权限(Permission) 用户 ↔ 角色 多对多关系 一个用户可有多个角色 角色 ↔ 权限 多对多关系,权限绑定在角色上 核心思想:用户不直接拥有权限,而是通过角色获得权限

从上图你可以看到,用户首先关联到角色,角色再关联到权限。这种分层结构,让权限变更的影响范围可控。你只要调整角色和权限的绑定,所有拥有该角色的用户就自动生效。