MySQL 系统学习 第五阶段:企业级 MySQL 实战开发 第二章:RBAC 权限系统设计
一、什么是 RBAC?
RBAC 全称:
Role-Based Access Control(基于角色的访问控制)
它的思想非常简单:
不给用户直接分配权限,而是先给用户分配角色,再给角色分配权限。
例如:
张三 │ ▼ 管理员 │ ▼ 拥有所有权限或者:
李四 │ ▼ 普通员工 │ ▼ 查看订单 查看商品 不能删除数据二、为什么不用直接给用户分配权限?
假设公司有:
- 1000 名员工
- 50 种权限
如果直接分配:
张三 ├── 查看用户 ├── 删除用户 ├── 添加商品 ├── 删除商品 ├── 查看订单 ...1000 人都要单独维护权限。
维护成本非常高。
使用 RBAC:
管理员 ├── 查看用户 ├── 删除用户 ├── 添加商品 ├── 删除商品 运营 ├── 查看商品 ├── 修改商品 客服 ├── 查看订单 ├── 修改订单用户只需要绑定角色:
张三 ↓ 管理员如果管理员权限变化:
只修改一次:
管理员角色所有管理员立即生效。
三、RBAC 的四个核心对象
整个 RBAC 可以抽象成四张核心表:
User(用户) Role(角色) Permission(权限) Menu(菜单,可选)企业中最常见的是:
User ↓ Role ↓ Permission四、用户(User)
用户就是登录系统的人。
例如:
| id | username |
|---|---|
| 1 | admin |
| 2 | tom |
| 3 | jack |
对应 SQL:
CREATE TABLE user( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50), password VARCHAR(255) );这里只保存:
- 登录账号
- 密码
- 手机号
- 邮箱
不要保存权限。
五、角色(Role)
角色代表:
一类人的身份。
例如:
| id | 角色 |
|---|---|
| 1 | 超级管理员 |
| 2 | 管理员 |
| 3 | 运营 |
| 4 | 客服 |
| 5 | 访客 |
SQL:
CREATE TABLE role( id BIGINT PRIMARY KEY AUTO_INCREMENT, role_name VARCHAR(50), role_code VARCHAR(50) );例如:
role_code ADMIN USER OPERATOR程序一般判断:
role_code而不是:
role_name因为:
名称可以修改:
管理员 ↓ 系统管理员code:
一般不会变。
六、权限(Permission)
权限:
表示:
系统允许做什么。
例如:
查看用户 新增用户 删除用户 修改用户 查看订单 删除订单SQL:
CREATE TABLE permission( id BIGINT PRIMARY KEY AUTO_INCREMENT, permission_name VARCHAR(100), permission_code VARCHAR(100) );例如:
permission_code user:list user:add user:delete order:list order:delete以后:
NestJS:
Guard:
就是判断:
permission_code七、为什么需要角色中间层?
很多新人会问:
为什么不能:
用户 ↓ 权限原因:
如果:
1000人。
每个人:
50权限。
需要:
50000条关系。
修改:
非常困难。
而:
用户 ↓ 角色 ↓ 权限权限:
只维护:
角色。
维护成本:
极低。
八、表之间关系
现在:
开始画关系。
一个用户:
可以有:
多个角色。
例如:
Tom ↓ 管理员 ↓ 运营所以:
User:
和:
Role:
是:
多对多角色:
和:
权限:
也是:
多对多例如:
管理员:
拥有:
用户管理 商品管理 订单管理运营:
拥有:
商品管理 订单查看所以:
Role:
Permission:
也是:
多对多。
九、为什么多对多不能直接存?
例如:
错误设计:
User:
id username rolerole:
ADMIN,USER问题:
SQL:
无法:
JOIN。
无法:
建立外键。
无法:
索引。
违反:
第一范式(1NF)。
所以:
需要:
中间表。
十、User 与 Role(多对多)
需要:
user_role:
CREATE TABLE user_role( user_id BIGINT, role_id BIGINT );例如:
| user_id | role_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
表示:
用户1 ↓ 管理员 ↓ 运营十一、Role 与 Permission(多对多)
同样:
建立:
CREATE TABLE role_permission( role_id BIGINT, permission_id BIGINT );例如:
| role_id | permission_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
十二、最终数据库结构
最终:
RBAC:
数据库:
User │ │ │ User_Role │ │ Role │ │ Role_Permission │ │ Permission或者画得更完整一点:
+---------+ +-------------+ +--------+ | User |<-------> | User_Role |<-------> | Role | +---------+ +-------------+ +--------+ | | v +------------------+ | Role_Permission | +------------------+ | | v +--------------+ | Permission | +--------------+十三、企业后台权限流程
用户登录:
输入账号密码↓
查询:
user↓
查询:
user_role↓
查询:
role_permission↓
得到:
permission↓
生成:
JWT。
以后:
每次请求:
判断:
permission_code例如:
user:add有:
允许。
没有:
403。
十四、本章总结
| 表 | 作用 |
|---|---|
| user | 用户 |
| role | 角色 |
| permission | 权限 |
| user_role | 用户角色关系 |
| role_permission | 角色权限关系 |
核心关系:
User ↓ Role ↓ Permission都是通过中间表建立多对多关系。
🎯 本章核心一句话:
RBAC 的核心思想是"用户拥有角色,角色拥有权限",通过角色作为中间层,实现权限的统一管理和灵活扩展。
本章思考题
- 为什么 RBAC 不直接把权限分配给用户,而要增加 Role(角色)这一层?
因为角色是权限的集合,增加角色这一层可以实现权限的统一管理,降低维护成本。 - 为什么 User 和 Role、Role 和 Permission 都设计成多对多关系?
用户可以有多个角色,角色可以有多个权限,因此两者都需要设计成多对多关系。 - 为什么多对多关系需要中间表,而不能把多个角色直接存到一个字段中?
中间表符合数据库范式,支持外键、索引和高效查询,是实现多对多关系的标准方式。 role_name和role_code有什么区别?为什么程序更适合使用role_code?
role_name 用于展示,role_code 用于程序判断,因为 code 稳定,不会因业务名称变化而影响代码。- 如果一个用户同时拥有两个角色,而两个角色都包含同一个权限,最终这个用户应该拥有几次这个权限?为什么?
多个角色的权限最终会取并集,并自动去重,同一个权限只会生效一次。