1. RBAC入门:从混乱到有序的权限管理之路
说实话,每次接手新项目,看到那种直接给用户绑权限的代码,我就头疼。你想想看,用户表里一堆权限字段,每次新增功能就得改数据库,这日子什么时候是个头?
RBAC 就是为了解决这种混乱而生的。它不是什么新概念,但直到今天,我依然认为它是企业级权限管理最优雅的方案之一。
1.1 RBAC 发展史:我见证的权限进化
RBAC 的历史,说白了就是权限管理从“野蛮生长”到“标准化”的过程。
- 90年代初:David Ferraiolo 和 Richard Kuhn 在美国国家标准局提出了 RBAC 的概念。当时主要为了统一政府机构的权限模型。
- 1992年:正式发表,第一次系统定义了“角色”这个中间层。
- 2004年:成为美国国家标准(ANSI INCITS 359-2004)。这也是我现在做设计时最常用的参考标准。
- 至今:衍生出 RBAC0、RBAC1、RBAC2、RBAC3 四个等级,逐步加入了角色继承、职责分离等高级特性。
一点个人经验:我实际项目中用得最多的是 RBAC0 加上一些 RBAC2 的约束规则。大部分业务场景下,一个基础模型加上合理的组织架构就够了。不要为了炫技而上复杂的继承体系,容易把自己坑进去。
1.2 三个核心概念:用户、角色、权限
这就是 RBAC 的精髓了——在“用户”和“权限”之间加一层“角色”。
| 概念 | 我把它理解成 | 真实项目中的例子 |
|---|---|---|
| 用户(User) | 干活的人 | 张三、李四,你的 App 里的某个账号 |
| 角色(Role) | 职位或岗位 | 管理员、运营专员、普通用户 |
| 权限(Permission) | 操作按钮或接口 | “创建订单”、“删除用户”、“查看报表” |
记住一个口诀:用户只能通过角色获得权限,角色是权限的集合。
我在项目中遇到过一个团队,他们让每个用户直接勾选一堆“操作”。权限多了以后,新增一个功能,要通知上百个用户去重新勾选……嗯,后来他们改用 RBAC 了。
为什么不用“用户-权限”直接绑定?
直接绑定不是不能用,但管理成本太高。你想想看:
- 100个用户、20种权限,直接绑就是100×20=2000条关系。
- 引入角色后,10个角色就能覆盖所有场景,每个角色关联权限,用户关联角色即可。
角色就是那个“稳定层”。权限变化频繁,但岗位和职责相对稳定。
1.3 应用场景:什么时候该上 RBAC?
不是所有系统都需要 RBAC。但我个人习惯,只要系统存在多用户、多数据、多操作这三个特征,我就直接上。因为后期重构的成本真的很高。
几个典型场景:
- SaaS 平台:不同租户拥有不同的管理角色,比如超级管理员、项目管理员、只读用户。
- 企业内部系统:OA、CRM、ERP,不同岗位看到不同菜单。
- 运营后台:运营、财务、客服,每个角色的操作边界清清楚楚。
避坑指南:我曾经见过一个团队,把“数据权限”和“功能权限”混在一起做。结果就是角色A能看到北京的全部订单,但看不到上海的。这种颗粒度的控制,光靠 RBAC 的基础模型是不够的,需要结合数据级权限的扩展设计。后面我会专门讲这个。
1.4 RBAC 的核心优势:我为什么推荐它
做 SDK 适配时,RBAC 的好处就更明显了:
- 解耦:SDK 只需要关心“角色-权限”的映射,不需要知道用户是谁。
- 可扩展:新增一种角色,SDK 这边配一套权限规则就好,不用改核心代码。
- 审计友好:查日志时,看到“角色A的权限被修改”,比看到“张三的权限被修改”更清晰——因为你知道这个角色下有好几十个人。
说白了,RBAC 就是一种降低认知复杂度的抽象手段。你不需要记住每个人的权限,记住几个角色就行。
重要提示:上图中的“会话”和“约束条件”在 RBAC0 基础模型中是可选的。但在 SDK 设计中,我会强烈建议把会话管理纳入进来,因为一个用户可以同时扮演多个角色,而会话决定了“当前上下文下,你激活了哪些角色”。这个细节在后期做鉴权拦截时非常关键。
1.5 一个简单的代码示例:如何定义模型
我在 SDK 里一般这样定义基础数据结构:
# 用户实体
class User:
def __init__(self, user_id, name):
self.user_id = user_id
self.name = name
self.roles = []
# 角色实体
class Role:
def __init__(self, role_id, name):
self.role_id = role_id
self.name = name
self.permissions = []
# 权限实体
class Permission:
def __init__(self, perm_code, name):
self.perm_code = perm_code
self.name = name
# 核心判断逻辑
def has_permission(user, perm_code):
for role in user.roles:
for perm in role.permissions:
if perm.perm_code == perm_code:
return True
return False
这个例子很基础,但核心思想到位了。实际项目中,我通常会把查询缓存起来,因为角色分配关系变化不频繁。
注意:一定要区分“角色ID”和“角色名称”。我在代码里用角色ID做关联,角色名称只做展示。为什么?因为你今天叫“管理员”,明天可能改叫“超级管理员”,如果代码里写了字符串匹配,那改起来就炸了。
1.6 小结:学了这章,你应该带走什么
- 三个概念:用户、角色、权限,角色是中间的桥梁。
- 一个关系:用户-角色-权限,三者构成 RBAC 的骨架。
- 一个原则:权限最小化,角色设计要符合业务实际。
好了,这就是 RBAC 的入门。下节课我们会深入到 RBAC 的几种标准模型,看看在不同的 SDK 场景里,我们该选 RBAC0 还是 RBAC2。嗯,到时候我会用一个真实的 SDK 项目踩坑案例来讲解。