RBAC 基础:角色定义、权限结构、最小权限原则
讲到权限控制,很多人第一反应就是“给用户分配权限”。但我见过太多项目,直接给用户打勾选权限,最后变成一团乱麻。RBAC(基于角色的访问控制)之所以被广泛采用,核心思路就是一句话:把权限和用户解耦,中间加一层“角色”。说白了,你不再直接告诉张三能不能删文件,而是先定义“管理员”这个角色,再把张三扔进去。
1. 角色定义:不是头衔,是权限的集合
角色到底是什么?我习惯这么理解:角色 = 一组权限的逻辑聚合。比如“审核员”这个角色,可能包含“查看待审数据”、“提交审核意见”、“驳回”三个权限。它不等于职位名称——项目里可以同时有“项目审核员”和“财务审核员”,权限完全不同。
角色之间还能继承。比如“高级管理员”继承“普通管理员”的所有权限,再加几个敏感操作。但继承深度不要超过3层,否则权限推理会变得极为复杂。我曾经接手过一个5层继承的项目,定位一个用户为什么能删除日志,追了三天——嗯,从那以后我坚决反对过度继承。
2. 权限结构:资源 × 操作 = 权限
权限的结构很简单:谁(主体)对什么(资源)能干什么(操作)。在 RBAC 里,主体是角色,资源可以是文件、接口、数据库表,操作通常是增、删、改、查、执行等。
我习惯把权限表设计成三元组:
| 资源类型 | 操作 | 权限标识 |
|---|---|---|
| 订单 | 查询 | order:read |
| 订单 | 修改 | order:update |
| 用户信息 | 导出 | user:export |
所有权限用字符串表示,方便存储和校验。角色和权限是多对多关系,中间表存角色ID和权限ID。结构清晰,也容易扩展——加一个新权限,只需在权限表加一行,再关联到角色。
3. 最小权限原则:给够,但别多给
最小权限原则(Least Privilege Principle)说的是:一个角色只应拥有完成其职责所必需的最少权限。举个例子,一个实习生只需要查看工单,就不该给他删除权限;一个运维人员只需要重启服务,就不该给他修改代码仓库的权限。
我在一次安全审计中遇到一个经典案例:某公司的所有开发人员都被赋予了“服务器管理员”角色,结果一个新手误操作删了生产数据库。追查下来,其实开发只需要部署和查看日志,根本不需要root权限。原因就是角色设计时太粗放——把“运维”和“开发”混在一个角色里。
怎么落地?我一般用下面三步:
- 职责分析: 列出每个岗位必须的操作,比如“财务审核员”需要“查看报销单”和“通过/驳回”。
- 权限拆分: 把每个操作拆成最小颗粒的权限。比如“查看”和“导出”是不同权限,不要合并。
- 角色模板化: 为每种职责创建角色模板,然后通过“角色-用户”映射分配给具体人。
有个技巧:新角色创建时,默认不分配任何权限,然后由审批者逐一勾选。这样可以避免“为了省事直接给个管理员角色”的坏习惯。
4. 为什么这对越权检测很重要?
越权漏洞的本质就是主体获得了超出角色定义的权限。你想想看,如果角色定义清楚,权限结构规整,最小权限落实到位,那么检测越权就变成了“检查用户当前操作是否在角色权限集合内”。
后面章节我们会深入讲具体检测方法:比如通过权限矩阵对比、动态权限校验、日志审计等。但基础打不好,检测工具再牛也白搭。我见过一个公司买了昂贵的审计系统,结果因为角色定义混乱,日志里全是“用户拥有意外权限”,根本分不清是人为越权还是设计缺陷。
上面这张图把 RBAC 三个核心元素串起来了:用户挂角色,角色挂权限,权限落资源。箭头方向就是权限分配的方向。注意审计员角色的虚线箭头——它只拥有部分权限,这正是最小权限原则的体现。
5. 一些实战经验
- 权限颗粒度别走极端: 我曾经把“查看”权限细分成“查看订单金额”和“查看订单状态”,结果角色配置页有200个checkbox,运维崩溃。通常一个资源4-6个操作就够。
- 角色数量控制: 超过50个角色时,一定要做角色合并和梳理。我建议用角色组(Role Group)把相近角色归类,例如“业务角色组”、“运维角色组”。
- 默认拒绝: 所有权限策略都应该白名单制——没明确允许的就是拒绝。这是最小权限的落地保障。