2. RBAC基础:角色、权限、用户模型

说起零信任的权限隔离,RBAC 几乎是绕不开的起点。我自己刚接触权限设计时,也踩过不少坑——最典型的就是把权限直接绑在用户身上,结果后期每来一个新需求都要改表结构,简直欲哭无泪。后来我才意识到,角色才是权限管理的核心枢纽。

这一节,我们就来拆解 RBAC 最基础的三个元素:用户、角色、权限。搞清楚它们之间的关系,你就能搭出一套可扩展、易维护的权限模型。

3.1 三个核心概念

先看一张表,快速区分它们:

概念英文定义我理解的本质
用户User系统的操作者,可以是人、服务账号、设备权限的最终承担者
角色Role一组权限的集合,代表一种职责或岗位权限的“容器”
权限Permission对某个资源执行特定操作的能力最细粒度的控制单元

这三个概念的关系,说白了就是一句话:用户通过角色获得权限。你想想看,如果直接给用户分配权限,一个项目几十个人,每个人都是独立的权限列表——维护成本会爆炸。加上角色这一层,权限管理和复用就优雅多了。

3.2 核心关系模型

RBAC 标准模型(也叫 RBAC0)定义了三个基本关系:

  • 用户-角色分配 (UA, User Assignment):一个用户可以拥有多个角色,一个角色也可以被多个用户拥有。多对多关系。
  • 角色-权限分配 (PA, Permission Assignment):一个角色可以包含多个权限,一个权限也可以出现在多个角色里。也是多对多。
  • 角色层级 (RH, Role Hierarchy):角色之间可以继承。比如“管理员”继承“操作员”的所有权限,再额外加一些管理权限。

下面这张图展示了它们之间的完整结构:

RBAC核心关系模型 用户 (User) 用户 (User) 用户 (User) 操作员 管理员 审计员 读权限 写权限 删除权限 继承 核心关系说明 UA(用户-角色分配):多对多 | PA(角色-权限分配):多对多 | RH(角色层级):角色可继承父角色权限
小技巧:在实际建模时,我习惯把角色层级限制在3层以内。超过3层,权限继承逻辑就容易混乱,排查问题时得一层层翻,脑仁疼。

3.3 如何落地:数据模型示例

拿关系型数据库来说,RBAC 通常需要五张核心表:

-- 用户表
CREATE TABLE `users` (
  `id`        INT PRIMARY KEY AUTO_INCREMENT,
  `username`  VARCHAR(64) NOT NULL UNIQUE,
  `enabled`   TINYINT(1) DEFAULT 1
);

-- 角色表
CREATE TABLE `roles` (
  `id`        INT PRIMARY KEY AUTO_INCREMENT,
  `name`      VARCHAR(64) NOT NULL UNIQUE,
  `parent_id` INT DEFAULT NULL,  -- 用于角色层级
  FOREIGN KEY (`parent_id`) REFERENCES `roles`(`id`)
);

-- 权限表
CREATE TABLE `permissions` (
  `id`         INT PRIMARY KEY AUTO_INCREMENT,
  `resource`   VARCHAR(128) NOT NULL,  -- 资源标识,如 "order:123"
  `action`     VARCHAR(32) NOT NULL,   -- 操作,如 "read"、"write"
  UNIQUE KEY `uk_res_act` (`resource`, `action`)
);

-- 用户-角色关联表
CREATE TABLE `user_roles` (
  `user_id` INT NOT NULL,
  `role_id` INT NOT NULL,
  PRIMARY KEY (`user_id`, `role_id`),
  FOREIGN KEY (`user_id`) REFERENCES `users`(`id`),
  FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`)
);

-- 角色-权限关联表
CREATE TABLE `role_permissions` (
  `role_id`       INT NOT NULL,
  `permission_id` INT NOT NULL,
  PRIMARY KEY (`role_id`, `permission_id`),
  FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`),
  FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`)
);

这个结构非常清晰。你想想看,以后要给某个部门新增一个“数据导出员”角色,只需要在roles表加一行,再给它分配几个权限就行。用户侧完全不用动。

3.4 避坑指南

我曾经犯过的错:角色层级用得太随意,让“普通用户”继承了“VIP用户”的部分权限,结果导致权限膨胀。后来我定了个规则:角色层级只用于“向上继承”,即子角色只能继承父角色的所有权限,不能反向或跨级。这样逻辑就干净多了。

另外,有个细节容易被忽视——静态职责分离(SSD)。比如一个用户不能同时拥有“采购员”和“审批员”角色,否则他就能自己采购自己审批,形成利益冲突。我一般在分配用户角色时做一次校验,不允许互斥角色同时出现。

3.5 小结

用户、角色、权限这三者的关系,就是 RBAC 的骨架。记住:角色是权限的容器,用户通过角色获得权限。建好这几张表,配合角色层级和互斥约束,你的权限系统就已经具备可扩展的基础了。