2. RBAC核心模型(RBAC0):用户、角色、权限三要素详解

RBAC0 是 RBAC 体系中最基础的模型,也是所有权限系统的起点。它定义了三个核心实体:用户(User)、角色(Role)、权限(Permission),以及它们之间的两层关联关系。理解 RBAC0,就等于掌握了权限设计的底层逻辑。

2.1 三要素定义

要素 英文 定义 典型示例
用户 User 系统的操作主体,通常对应一个人或一个服务账号 张三(工号 1001)、客服机器人
角色 Role 权限的集合,代表一类职责或岗位 管理员、运营编辑、普通访客
权限 Permission 对某个资源执行某种操作的许可 「创建订单」「删除文章」「查看报表」
核心原则:用户不直接与权限挂钩,而是通过「角色」作为中间层间接获得权限。这一层抽象是 RBAC 灵活性的根源。

2.2 用户 ↔ 角色 ↔ 权限 的关联关系

RBAC0 的关联关系可以概括为两条线:

  1. 用户-角色关联(User-Role Assignment, UA):一个用户可以拥有多个角色,一个角色也可以被多个用户持有。这是多对多关系。
  2. 角色-权限关联(Role-Permission Assignment, PA):一个角色可以包含多个权限,一个权限也可以被多个角色引用。这也是多对多关系。

通过这两层映射,最终形成 用户 → 角色 → 权限 的授权链路。当判断用户是否有权执行某操作时,系统只需检查该用户的所有角色中,是否至少有一个角色包含了该操作对应的权限。

数学表达:
设 U = {用户集合},R = {角色集合},P = {权限集合}。
UA ⊆ U × R(用户-角色分配关系)
PA ⊆ R × P(角色-权限分配关系)
用户 u 拥有的权限集合 = { p | ∃ r ∈ R, (u, r) ∈ UA 且 (r, p) ∈ PA }
RBAC0 核心模型:用户-角色-权限关联关系 RBAC0 核心模型:用户 ↔ 角色 ↔ 权限 用户 (User) 张三 李四 王五 (操作主体) 角色 (Role) 管理员 运营编辑 普通访客 (权限集合) 权限 (Permission) 创建订单 删除文章 查看报表 (操作许可) UA 多对多 PA 多对多 授权链路:用户 → 角色 → 权限(用户通过角色间接获得权限)

2.3 为什么需要角色这一层?

如果不引入角色,直接让用户与权限关联(即 User-Permission 直连),会出现以下问题:

  • 管理爆炸:1000 个用户 × 50 个权限 = 50000 条关联记录,维护成本极高。
  • 变更困难:当某个岗位的职责发生变化时,需要逐一修改每个相关用户的权限,极易遗漏。
  • 缺乏语义:权限列表无法表达「这个人是什么岗位」,审计和合规检查困难。

引入角色后,上述问题迎刃而解:

  • 批量管理:只需维护 10 个角色 × 50 个权限 = 500 条关联,再为 1000 个用户分配角色即可。
  • 变更隔离:修改角色的权限集合,所有持有该角色的用户自动生效。
  • 语义清晰:角色名称直接反映职责(如「财务审核员」),便于审计和权限梳理。
常见误区:有些团队在初期为了「省事」,直接给每个用户单独配置权限,导致后期权限混乱、无人敢清理。请记住:没有角色层的权限系统,本质上不是 RBAC。

2.4 权限的粒度:操作 + 资源

在 RBAC0 中,权限通常由两个维度组成:

维度 说明 示例值
操作(Action) 对资源执行的行为 create, read, update, delete (CRUD)
资源(Resource) 被操作的对象 订单、文章、用户、报表

一个完整的权限可以表示为 操作:资源 的组合,例如:

order:create      # 创建订单
article:delete    # 删除文章
report:view       # 查看报表
user:update       # 修改用户信息

在数据库设计中,权限表通常包含 action 和 resource 两个字段,或者直接使用字符串标识(如 order.create)。

2.5 数据模型设计(核心表结构)

基于 RBAC0 的三要素和两层关联,数据库至少需要以下 5 张表:

表名 说明 关键字段
user 用户表 id, username, password, status
role 角色表 id, name, description
permission 权限表 id, action, resource, description
user_role 用户-角色关联表 user_id, role_id
role_permission 角色-权限关联表 role_id, permission_id
建表 SQL 示例(MySQL):
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(64) NOT NULL,
  `password` varchar(256) NOT NULL,
  `status` tinyint(4) DEFAULT '1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `description` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `permission` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `action` varchar(32) NOT NULL,
  `resource` varchar(64) NOT NULL,
  `description` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_action_resource` (`action`, `resource`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `user_role` (
  `user_id` bigint(20) NOT NULL,
  `role_id` bigint(20) NOT NULL,
  PRIMARY KEY (`user_id`, `role_id`),
  KEY `idx_role_id` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE `role_permission` (
  `role_id` bigint(20) NOT NULL,
  `permission_id` bigint(20) NOT NULL,
  PRIMARY KEY (`role_id`, `permission_id`),
  KEY `idx_permission_id` (`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
RBAC0 数据库核心表结构 ER 图 RBAC0 数据库核心表结构(5 表模型) user id (PK) username user_role user_id (FK) role_id (FK) role id (PK) name role_permission role_id (FK) permission_id (FK) permission id (PK) action, resource user_role 和 role_permission 为多对多关联表,分别实现 UA 和 PA

2.6 权限判断逻辑(伪代码)

在运行时,判断用户是否拥有某个权限的典型流程如下:

// 判断用户 user 是否拥有 action:resource 权限
boolean hasPermission(User user, String action, String resource) {
    // 1. 查询用户的所有角色
    List<Role> roles = userRoleMapper.findRolesByUserId(user.getId());

    // 2. 查询这些角色拥有的所有权限
    List<Permission> permissions = rolePermissionMapper
        .findPermissionsByRoleIds(roles.stream().map(Role::getId).collect(toList()));

    // 3. 判断目标权限是否在集合中
    return permissions.stream()
        .anyMatch(p -> p.getAction().equals(action)
                     && p.getResource().equals(resource));
}
性能优化提示:生产环境中不建议每次请求都查数据库。通常的做法是:用户登录后,将其所有权限缓存到 Redis(如 Set 结构),判断时直接查缓存,O(1) 时间复杂度。

2.7 本章小结

  • RBAC0 定义了 用户、角色、权限 三个核心实体,以及 UA(用户-角色) 和 PA(角色-权限) 两层多对多关联。
  • 角色作为中间层,实现了权限的批量管理、变更隔离和语义化,是 RBAC 灵活性的基石。
  • 权限由 操作 + 资源 两个维度构成,数据库设计至少需要 5 张表来支撑完整模型。
  • 权限判断的核心逻辑是:用户 → 角色 → 权限 的链路查询。