2、RBAC 核心原理:用户 · 角色 · 权限三要素及关系
权限系统的第一课——把“谁”能“做什么”说清楚。
RBAC(Role-Based Access Control)之所以流行,是因为它用了一个很朴素的中间层:角色。我个人觉得,这个设计是权限模型里最聪明的点子——它让权限管理从“人盯人”变成了“角色盯权限”。
2.1 三要素定义
先拆开看三个东西分别是什么。
用户(User) —— 系统的访问主体。可以是一个人,一个服务账号,甚至一个 IoT 设备。
角色(Role) —— 权限的集合,代表一类职责。比如“管理员”、“编辑”、“只读用户”。
权限(Permission) —— 对某个资源的操作许可。比如“创建订单”、“删除用户”、“查看报表”。
你想想看,如果不引入角色,我们需要给每个用户直接挂权限。一个公司 1000 人,每个人权限都不完全一样,管理起来就是噩梦。我在项目中遇到过一家企业,他们最初就是用户直挂权限,后来离职人员权限清理不干净,造成了严重的数据泄露。
所以 RBAC 说:别让用户直接和权限绑定,中间加一个角色层。
2.2 三要素的关系
关系其实就三条线:
- 用户 ↔ 角色:多对多。一个用户可以有多个角色,一个角色可以包含多个用户。
- 角色 ↔ 权限:多对多。一个角色可以拥有多个权限,一个权限也可以归属多个角色。
- 用户 ↔ 权限:间接关联。用户通过角色获得权限,不直接绑定。
说白了,角色就是中间商,但它不赚差价,只做“权限合并”。
👍 记忆口诀:用户扮演角色,角色拥有权限,用户继承权限。
2.3 为什么非要多加一层角色?
我刚开始学 RBAC 时也觉得多一层好麻烦。直到自己动手管过几千个用户的权限,才明白这层的价值:
- 批量管理:改角色权限,所有关联用户自动生效。不用一个个改。
- 职责分离:可以定义“出纳”和“会计”两个角色,确保一个人不能同时兼任。
- 最小权限原则:角色只给完成本职工作所需的最小权限集。
我曾经帮一家金融客户做权限审计,发现他们给一个实习生分配了“超级管理员”角色,就因为没经过角色隔离。嗯,那周我加了三天班帮他们重建角色体系。
所以我的建议是:哪怕系统初期只有几十个用户,也先把角色层搭起来。一旦业务膨胀,拆起来成本极高。
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 核心逻辑关系图
下面这张图把三要素和它们的关系画清楚了。箭头方向表示“拥有”或“属于”,你看一眼就能记住:
2.7 实际落地中的注意点
光懂概念还不够,我分享几个实战经验:
- 角色命名要规范:我见过“角色1”、“角色2”这种命名法,后来谁都不知道哪个是干什么的。建议用“功能域_角色名”格式,例如
order_admin、report_viewer。 - 角色数量控制:一般一个系统 5~15 个角色就够了,超过 20 个就要反思是不是权限粒度过细。
- 权限定义要原子化:每个权限只代表一个操作,不要把“增删改查”塞到一个权限里。
- 用户-角色关系要留审计日志:谁在什么时间给什么用户分配了什么角色,必须能追溯。我曾经在审计时被问到“上周谁把管理员角色给了那个离职员工”,幸好系统里记录了操作人,不然又得背锅。
💡 小技巧:在数据库设计时,把 user_roles 表的联合主键设为 (user_id, role_id),并在 created_at 和 creator 字段上建索引。查权审计时很香。