## 1、RBAC基础概念:用户、角色、权限三元组关系模型 ### 为什么权限这么难管? 我在一次金融系统的权限审计项目中,发现了一个“经典场面”。 项目组有60多个微服务,每个服务的接口权限写在各自的配置文件里。新员工入职,运维要手动配七八个系统的权限;员工转岗,得通知所有系统管理员逐个修改。更糟的是,有位同事离职三个月了,OA、CRM、GitLab上竟然都还挂着他的账号。 当时我就在想——为什么会出现这种混乱? 说白了,直接给“用户”授予“权限”这条路,在稍微复杂一点的组织里根本走不通。你想想看,一个中型公司可能有几百个用户、数千个接口、几十个业务系统。如果每个用户的权限都要单独配置,光维护成本就能拖垮整个运维团队。 RBAC(Role-Based Access Control)就是为了解决这个困境而生的。 ### 核心模型:用户-角色-权限 RBAC的精髓只有一句话:**用户不直接拥有权限,而是通过角色获得权限**。 这听起来简单,但真正理解它的人并不多。我曾经面试过一个自称“玩透RBAC”的候选人,让他画一下核心模型,他画出了四个实体、六张表、十几个关联关系。我问他:“你做的到底是访问控制还是数据库设计?”他愣住了。 RBAC的原始模型其实只有三个核心元素:
**用户(User)** + **角色(Role)** + **权限(Permission)** = **三元组关系模型**
具体来说: - **用户**:访问系统的主体。可以是一个人、一个服务账号、一个API消费者。用户的属性天生不稳定——入职、转岗、离职,这些变化每天都在发生。 - **角色**:权限的分组容器。它代表组织内的一类职责,比如“数据库管理员”、“订单审核员”。角色是稳定的,一个公司的职责划分通常几年才变一次。 - **权限**:对系统资源的操作能力。比如“创建订单”、“读取用户信息”、“删除服务器”。权限通常直接对应到系统的某个功能或接口。 它们之间的关系只有两个: 1. **用户关联角色**(多对多关系) 2. **角色拥有权限**(多对多关系) **用户与权限之间没有直接关联。这是整个RBAC模型的红线。** 用户-角色-权限三元组关系模型 用户 User 角色 Role 权限 Permission N 关联 N 拥有 角色是权限的容器 一个角色 = 一组权限的集合 用户通过角色间接获得权限 用户 → 角色(多对多) 一个用户可以有多个角色 角色 → 权限(多对多) 一个角色可以有多个权限 ### 为什么需要角色这个中间层? 我当年刚接触RBAC时也有这个疑问。直接给用户分配权限不是更直接吗?为什么要多搞一个“角色”出来? 后来在为一个电商平台做权限改造时,我彻底想明白了。
**直接授权的问题**: 假设公司有50个运营人员,每个人都需要“查看订单”和“导出报表”的权限。如果直接授给用户: - 这50个人每人要配2个权限 = 100次操作 - 如果这50个人配置完全一样,就会产生50份重复数据 - 当“导出报表”这个权限需要升级或废弃时,要通知50个人
现在用角色来管理: - 创建“运营专员”角色,赋予“查看订单”+“导出报表”权限 - 把50个运营人员都挂到这个角色上 - 权限变更时,只需要改角色,50个人自动生效 这就是RBAC的精髓——**对权限的变更进行集中化管理**。
**我曾经踩过的一个坑**: 有个遗留系统,表结构里直接设计了`user_permission`表,存了用户和权限的直接关联。后来业务扩张,用户数从100涨到10000,这张表膨胀到近百万条记录,权限变更时DBA叫苦连天。 我当时意识到:**任何绕开角色层的设计,在规模扩大后都会出问题**。只要是直接授给用户权限的地方,将来一定是灾难。
### 角色可以叠加吗? 可以,而且很多场景都需要角色叠加。 比如一个用户既是“开发工程师”,又是“项目管理员”。前者只能看代码、提MR,后者可以创建分支、管理版本发布。这个人同时拥有两个角色的全部权限。 这就是角色的核心价值:**组合和复用**。 ### 一张表看懂模型对比 | 特性 | 直接授权 | 基于角色的授权 | |------|---------|---------------| | 维护成本 | 用户数 × 权限数 | 角色数 + 用户与角色的关联 | | 权限变更影响 | 每个用户单独改 | 只改角色,用户自动更新 | | 扩展性 | 差,1000用户时已无法维护 | 好,支持万级用户 | | 权限审计 | 需要扫全表关联 | 只需要查角色定义 | | 典型场景 | 小工具、原型系统 | 企业级系统、微服务架构 | ### 我习惯怎么定义这几个概念? 在实际项目中,我一般这样定义: - **用户**:用人话来说,就是“谁”在操作。用唯一标识符表示,比如员工ID、邮箱、AK/SK。 - **角色**:描述“这类人”是干什么的。比如“运维主管”代表可以登录服务器、查看日志、重启服务;“财务审核”代表只能查看待审核的报销单。 - **权限**:描述“能干什么”。在接口层面,权限通常表示为`HTTP方法 + 资源路径`,比如`POST /api/orders`、`GET /api/reports`。 ### 从理论到实践的第一步 在你开始写代码之前,先做这件事:**把你的业务系统中的所有功能点列出来,分门别类,抽象成角色**。 这步工作决定了你的权限体系是否灵活、是否可持续。RBAC不是数据库设计,而是组织管理的映射。 好了,关于用户-角色-权限的三元组关系,今天就聊到这里。记住这个核心模型,后面的所有内容——包括角色继承、约束条件、权限缓存、接口映射——都是在这个基础上延伸出来的。