本文目录导读:

这是一个非常核心的后端与系统设计知识点。RBAC (Role-Based Access Control,基于角色的访问控制) 是目前企业级应用中最广泛使用的权限管理模型。
下面我为你系统地梳理 RBAC 的核心概念、典型模型、数据库设计以及最佳实践。
核心概念(四个基本要素)
RBAC 的核心思想是:将“权限”授予“角色”,再将“角色”授予“用户”,用户通过其拥有的角色来间接获得权限。
- 用户 (User):系统的操作者,张三、李四。
- 角色 (Role):权限的集合,是用户和权限之间的桥梁,管理员、编辑、普通用户。
- 权限 (Permission):对系统资源的操作许可,创建文章、删除用户、查看报表,通常定义为 资源 + 操作 (如
article:create)。 - 会话 (Session):用户激活的角色集合,用户登录后,系统为其创建一个会话,在该会话中激活其拥有的一个或多个角色。
标准 RBAC 模型(RBAC0)
这是最基础的模型,它规定了最基本的用户-角色-权限关系。
用户 (User) ----<多对多>---- 角色 (Role) ----<多对多>---- 权限 (Permission)
- 关系:
- 一个用户可以拥有多个角色。
- 一个角色可以包含多个用户。
- 一个角色可以拥有多个权限。
- 一个权限可以被多个角色拥有。
工作原理:系统检查“用户 -> 角色 -> 权限”这条链路,如果用户所属的某个角色拥有执行某个操作的权限,则允许访问。
RBAC 的进阶模型
在实际业务中,RBAC0 往往不够用,衍生出了以下三种扩展模型:
RBAC1(角色分级模型)
引入了角色继承 (Role Hierarchy) 概念,高级角色自动继承低级角色的所有权限。
- 示例:
超级管理员继承管理员,管理员继承编辑,编辑继承普通用户。 - 优势:简化了权限管理,你只需给
普通用户分配基础权限,编辑只需额外分配编辑权限,无需重复配置基础权限。 - 注意:继承可以是严格的(树形),也可以是部分的(图形),但通常建议使用树形以避免循环依赖。
RBAC2(角色约束模型)
在 RBAC0 基础上增加了约束 (Constraints) 机制,解决安全性问题。
- 互斥角色 (Mutually Exclusive Roles):一个用户不能同时拥有两个互斥的角色。
会计和出纳不能是同一个人;系统管理员和安全审计员不能是同一个人。 - 基数约束 (Cardinality Constraints):一个角色最多能被多少个用户拥有。
总经理角色最多只能有 1 人。 - 先决条件角色 (Prerequisite Roles):用户必须先拥有角色 A,才能拥有角色 B,必须是
高级会员才能成为VIP客服。
RBAC3(统一模型)
RBAC3 = RBAC1 + RBAC2,既支持角色继承,又支持角色约束,这是最复杂的模型,适用于大型、高安全性的系统。
数据库设计(经典5张表)
这是最标准、最常用的 RBAC 数据库设计(支持 RBAC0)。
-- 1. 用户表
CREATE TABLE `users` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) UNIQUE NOT NULL,
`password` VARCHAR(255) NOT NULL,
`status` TINYINT DEFAULT 1 -- 1:正常, 0:禁用
);
-- 2. 角色表
CREATE TABLE `roles` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(50) UNIQUE NOT NULL, -- admin, editor, user
`description` VARCHAR(255)
);
-- 3. 权限表 (资源 + 操作)
CREATE TABLE `permissions` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL, -- 创建文章, 删除用户
`resource` VARCHAR(50) NOT NULL, -- article, user
`action` VARCHAR(50) NOT NULL, -- create, delete, view
`description` VARCHAR(255),
UNIQUE KEY `uk_resource_action` (`resource`, `action`)
);
-- 4. 用户-角色关联表 (多对多)
CREATE TABLE `user_roles` (
`user_id` BIGINT NOT NULL,
`role_id` BIGINT NOT NULL,
PRIMARY KEY (`user_id`, `role_id`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`),
FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`)
);
-- 5. 角色-权限关联表 (多对多)
CREATE TABLE `role_permissions` (
`role_id` BIGINT NOT NULL,
`permission_id` BIGINT NOT NULL,
PRIMARY KEY (`role_id`, `permission_id`),
FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`),
FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`)
);
如果需要支持 RBAC1(角色继承),可以在 roles 表中增加一个 parent_id 字段(自引用外键)。
权限校验流程(后端核心逻辑)
当用户发起一个请求(POST /api/articles)时:
- 身份认证:验证用户身份(登录状态、Token)。
- 获取用户角色:根据
user_id查询user_roles表,获取用户拥有的所有role_id。 - 获取角色权限:根据这些
role_id查询role_permissions表,获取所有权限的集合(或缓存)。 - 权限匹配:获取请求对应的
资源 (resource)和操作 (action)(article,create),构造权限标识符(如article:create)。 - 决策:
- 如果用户的权限集合中包含该标识符,放行。
- 如果不包含,拒绝访问(403 Forbidden)。
优势与劣势
| 优势 | 劣势 |
|---|---|
| 管理高效:用户量巨大时,只需修改角色权限,所有用户生效。 | 粒度较粗:如果需要对“张三的某篇文章”进行特殊权限控制(行级/实例级权限),RBAC 很难直接支持。 |
| 安全性强:职责分离(互斥角色)防止权限滥用。 | 角色爆炸:业务复杂时,角色数量会激增,难以维护(例如每个部门都需要一个“经理”角色,导致角色数量过多)。 |
| 易于审计:用户-角色-权限关系清晰,方便追责。 | 静态定义:角色和权限通常是预定义的,动态、临时性的授权(如“允许李四查看这份报表一天”)实现起来较麻烦。 |
| 复用性高:角色是标准化的,可以跨部门或项目复用。 |
实际应用中的扩展与变体
- RBAC + 组织架构:很多系统(如企业级SaaS)会将 RBAC 与
组织/部门/岗位结合,权限不仅来源于直接分配的角色,还来源于用户所在的部门、岗位继承的角色。 - 角色分组:当角色过多时,可以引入
角色组 (Role Group)来对角色进行归类和管理。 - 数据权限(行级权限):RBAC 主要管“能不能做”(功能权限),不直接管“能做哪些数据”(数据权限)。“编辑”角色可以看文章,但只能看本部门的文章。
- 解决方案:在权限中增加数据范围字段(如:本人、本部门、全公司),或者在代码层面硬编码过滤逻辑,这是比 RBAC 更复杂的领域。
- RBAC0:基础模型,绝大多数系统够用。
- RBAC1:需要角色继承时使用(如复杂的后台管理系统)。
- RBAC2:需要职责分离、安全约束时使用(如金融、医疗系统)。
- 数据库:五张表(用户、角色、权限 + 两张关联表)是标配。
- 核心思想:权限赋给角色,角色赋给用户。
在实际开发中,推荐从 RBAC0 开始,用 5张表 落地,然后根据业务复杂度逐步引入继承、约束或组织架构。