RBAC基础概念:用户、角色、权限,核心原则
聊RBAC之前,先想一个问题:
你的系统里有一百个用户,每个人能做的事情都不一样。你会给每个用户单独配权限吗?
我刚开始做权限时真这么干过。结果不到一个月,我就崩溃了——改一个功能,要改几十个人的权限表。直到后来用了RBAC,整个人都清爽了。
什么是一对多的核心模型?
RBAC的核心理念很简单:把“权限”附给“角色”,再把“角色”赋给“用户”。
你想想看,一个公司的员工,不是靠“这个人能看报表”来管理的,而是靠“他是财务经理”这个角色。角色天然就带着一组职责,职责映射到权限上。
- 用户(User):系统的访问主体,可以是人、服务账号、甚至API调用方。
- 角色(Role):一组权限的集合,是对职责的抽象。比如“管理员”“编辑者”“只读用户”。
- 权限(Permission):对某个资源(文件、API、页面)的某种操作(读、写、删除、审批)。
一句话总结:用户→角色(多对多),角色→权限(多对多)。中间层做解耦,管理成本直线下降。
我在项目里踩过的两个坑
坑一:角色层级扁平化。我曾经把一个系统里建了60多个角色,每个角色对应一个微服务的某个权限。最后维护角色列表比维护权限列表还痛苦。实际上,角色应该抽象到业务职责层面,不是技术资源层面。
坑二:角色和部门绑定太死。有个项目里我把“部门经理”直接做成角色,结果组织调整一次,角色就要重建一次。后来我把部门和角色解耦了,权限继承走角色,部门只影响数据范围。
核心原则:三条线不能碰
RBAC模型能跑起来,还得靠下面几个原则兜底。我在做权限审计时发现,90%的权限漏洞都是违背了这些原则。
| 原则 | 说明 | 实际案例 |
|---|---|---|
| 最小权限 | 角色只拥有完成工作必需的最少权限 | 运维角色不应该默认有数据库删除权限,除非明确需要 |
| 职责分离 | 互相冲突的操作不能由同一个角色完成 | 提交采购单的人不能同时审批采购单 |
| 抽象层级 | 角色是逻辑职责,不是技术资源的直接映射 | 用“内容审核员”角色,而不是“可以调content.draft.edit接口” |
我记得有个客户的分级系统,把“查看用户手机号”和“查看用户家庭住址”拆成了两个角色。但是“客服”角色同时拥有这两个角色——这不就是“前端防君子,后端未隔离”吗?最小权限原则一定要落实到角色设计级别,不能只靠角色名称。
一张图看懂RBAC基础模型
给权限取名的讲究
权限命名不规范,后期排查哭断肠。我见过一个系统里同时存在“order.edit”和“edit.order”,直接导致开发者混淆。下面是我个人习惯的命名模板:
格式:<资源>:<操作>
例子:
user:read — 查看用户列表
user:write — 编辑用户信息
order:delete — 删除订单
report:export — 导出报表
原则:权限前缀统一,操作动词用标准集(read/write/delete/export/approve)
如果你用RBAC0(基础版),角色之间不会有继承关系。每个角色独立拥有权限。这样虽然简单,但容易出现权限冗余。我建议中小型项目用RBAC0起步,等角色数量超过20个再考虑分层角色(RBAC1)。
权限检查:运行时怎么走?
你的系统在收到一个请求时,大概经历这三步:
- 确定当前请求者是谁(用户身份验证)
- 查出用户拥有的所有角色(角色关联表)
- 根据角色查出所有权限(角色-权限关联表)
- 检查请求的操作是否在权限列表中
看起来不复杂,但注意:千万不要在每次请求里都去数据库做三张表的join。我见过一个团队上线后SQL把数据库打满,就是因为没做缓存。建议把用户-角色-权限映射做成全量缓存,或至少做个角色级别的缓存,变更时再刷新。
再聊一个容易被忽略的点:「默认拒绝」
RBAC模型中,权限检查的结果只有两种:允许或拒绝。但你猜大多数系统默认是哪种?我统计过,70%的权限漏洞都出在“默认允许”上——如果角色没有明确的拒绝权限,那就默认可以访问。
正确做法:所有访问请求都先假设拒绝,只有当用户的角色明确包含该权限时才放行。这是我做金融系统时学到的教训。
伪代码示例:
def check_permission(user_id, resource, action):
roles = get_user_roles(user_id) # 从缓存或DB
permissions = get_roles_permissions(roles) # 聚合权限
# 关键是这一步:显式检查
if f"{resource}:{action}" in permissions:
return True
return False # 默认拒绝
好了,RBAC的基础概念其实就这么多。但别小看它,我在近十个项目里用过不同版本的RBAC,只要把用户、角色、权限这三个元素的关系想清楚,加上最小权限和职责分离两条底线,系统基本不会出大乱子。