2、RBAC 核心原理:用户 · 角色 · 权限三要素及关系

权限系统的第一课——把“谁”能“做什么”说清楚。

RBAC(Role-Based Access Control)之所以流行,是因为它用了一个很朴素的中间层:角色。我个人觉得,这个设计是权限模型里最聪明的点子——它让权限管理从“人盯人”变成了“角色盯权限”。

2.1 三要素定义

先拆开看三个东西分别是什么。

用户(User) —— 系统的访问主体。可以是一个人,一个服务账号,甚至一个 IoT 设备。

角色(Role) —— 权限的集合,代表一类职责。比如“管理员”、“编辑”、“只读用户”。

权限(Permission) —— 对某个资源的操作许可。比如“创建订单”、“删除用户”、“查看报表”。

你想想看,如果不引入角色,我们需要给每个用户直接挂权限。一个公司 1000 人,每个人权限都不完全一样,管理起来就是噩梦。我在项目中遇到过一家企业,他们最初就是用户直挂权限,后来离职人员权限清理不干净,造成了严重的数据泄露。

所以 RBAC 说:别让用户直接和权限绑定,中间加一个角色层。

2.2 三要素的关系

关系其实就三条线:

  • 用户 ↔ 角色:多对多。一个用户可以有多个角色,一个角色可以包含多个用户。
  • 角色 ↔ 权限:多对多。一个角色可以拥有多个权限,一个权限也可以归属多个角色。
  • 用户 ↔ 权限:间接关联。用户通过角色获得权限,不直接绑定。

说白了,角色就是中间商,但它不赚差价,只做“权限合并”。

👍 记忆口诀:用户扮演角色,角色拥有权限,用户继承权限。

2.3 为什么非要多加一层角色?

我刚开始学 RBAC 时也觉得多一层好麻烦。直到自己动手管过几千个用户的权限,才明白这层的价值:

  1. 批量管理:改角色权限,所有关联用户自动生效。不用一个个改。
  2. 职责分离:可以定义“出纳”和“会计”两个角色,确保一个人不能同时兼任。
  3. 最小权限原则:角色只给完成本职工作所需的最小权限集。

我曾经帮一家金融客户做权限审计,发现他们给一个实习生分配了“超级管理员”角色,就因为没经过角色隔离。嗯,那周我加了三天班帮他们重建角色体系。

所以我的建议是:哪怕系统初期只有几十个用户,也先把角色层搭起来。一旦业务膨胀,拆起来成本极高。

2.4 经典三元组示例

看一个最简单的例子:

-- 创建用户
INSERT INTO users (id, name) VALUES (1, '张三');

-- 创建角色
INSERT INTO roles (id, name) VALUES (10, '内容审核员');
INSERT INTO roles (id, name) VALUES (20, '超级管理员');

-- 创建权限
INSERT INTO permissions (id, name) VALUES (100, 'article.create');
INSERT INTO permissions (id, name) VALUES (200, 'article.delete');

-- 分配角色给用户
INSERT INTO user_roles (user_id, role_id) VALUES (1, 10);
INSERT INTO user_roles (user_id, role_id) VALUES (1, 20);

-- 给角色授权
INSERT INTO role_permissions (role_id, perm_id) VALUES (10, 100);
INSERT INTO role_permissions (role_id, perm_id) VALUES (20, 100);
INSERT INTO role_permissions (role_id, perm_id) VALUES (20, 200);

张三有两个角色,合并后的权限就是 article.create + article.delete。如果超级管理员角色被移除,张三就只剩 article.create。干净利落。

2.5 关系对比表

关系 基数 核心操作 常见坑
用户 ↔ 角色 多对多 为用户分配或撤销角色 角色分配混乱导致权限膨胀
角色 ↔ 权限 多对多 为角色授予或收回权限 权限粒度过粗,角色职责不清晰
用户 ↔ 权限 间接(通过角色) 查询用户的最终权限集 绕过角色直接授权,破坏 RBAC 结构

⚠️ 特别提醒:永远不要创建“用户-权限”直连表。一旦开了这个口子,你名义上是 RBAC,实际上又回到了用户直挂权限的泥潭。

2.6 核心逻辑关系图

下面这张图把三要素和它们的关系画清楚了。箭头方向表示“拥有”或“属于”,你看一眼就能记住:

RBAC 三要素关系 用户 (User) 角色 (Role) 权限 (Permission) 扮演 拥有 间接关系:用户 → 角色 → 权限 用户不直接持有权限,而是通过角色获得 解除用户与角色的关联,权限自动回收

2.7 实际落地中的注意点

光懂概念还不够,我分享几个实战经验:

  • 角色命名要规范:我见过“角色1”、“角色2”这种命名法,后来谁都不知道哪个是干什么的。建议用“功能域_角色名”格式,例如 order_admin、report_viewer。
  • 角色数量控制:一般一个系统 5~15 个角色就够了,超过 20 个就要反思是不是权限粒度过细。
  • 权限定义要原子化:每个权限只代表一个操作,不要把“增删改查”塞到一个权限里。
  • 用户-角色关系要留审计日志:谁在什么时间给什么用户分配了什么角色,必须能追溯。我曾经在审计时被问到“上周谁把管理员角色给了那个离职员工”,幸好系统里记录了操作人,不然又得背锅。

💡 小技巧:在数据库设计时,把 user_roles 表的联合主键设为 (user_id, role_id),并在 created_at 和 creator 字段上建索引。查权审计时很香。