3. 授权模型:RBAC、ABAC、PBAC 详解与选型策略
授权模型这东西,说白了就是「谁在什么条件下能干什么事」。我在接口适配项目里踩过不少坑,最惨的一次是权限模型没选对,导致后期改了整整两周的适配层代码。今天我把三种主流模型掰开揉碎讲清楚,顺便聊聊在接口适配场景下该怎么选。
3.1 RBAC:基于角色的访问控制
RBAC 是最经典的授权模型。它的核心思路很简单:把权限打包成角色,再把角色分配给用户。
核心公式:用户 → 角色 → 权限
举个例子。一个电商系统的接口适配层,可能有这些角色:
- 普通用户:只能查自己的订单、修改个人信息
- 客服:可以查所有用户的订单,但不能改价格
- 运营:可以管理商品上下架、设置促销活动
- 管理员:啥都能干
在接口适配中,RBAC 的实现通常长这样:
// 接口适配层的 RBAC 校验示例
public class RbacAuthorizationFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 从 token 中提取用户角色
String role = extractRole(exchange.getRequest());
// 2. 获取当前请求路径对应的权限标识
String permission = getPermissionByPath(exchange.getRequest().getURI().getPath());
// 3. 校验角色是否拥有该权限
if (!hasPermission(role, permission)) {
return Mono.error(new AuthorizationException("权限不足"));
}
return chain.filter(exchange);
}
private boolean hasPermission(String role, String permission) {
// 实际项目中这里会查 Redis 或本地缓存
Map<String, Set<String>> rolePermissions = loadRolePermissions();
return rolePermissions.getOrDefault(role, Collections.emptySet())
.contains(permission);
}
}
我的经验:RBAC 最适合角色相对稳定的场景。我在一个内部管理系统里用过,角色不超过 20 个,权限配置一目了然。但如果你有几千个用户,每个用户都需要定制权限,RBAC 就会变得很痛苦——角色会膨胀到难以管理。
3.2 ABAC:基于属性的访问控制
ABAC 比 RBAC 灵活得多。它不看「你是什么角色」,而是看「你、资源、环境都有什么属性」。
ABAC 的决策公式是:
允许访问 = 主体属性 AND 资源属性 AND 环境属性 AND 操作类型
举个例子。在接口适配层,一个 ABAC 策略可能是这样:
- 主体属性:用户部门 = "销售部",职级 >= "P7"
- 资源属性:数据敏感级别 = "机密"
- 环境属性:访问时间 = "工作时间",IP 段 = "内网"
- 操作类型:查询
只有同时满足以上所有条件,才允许访问。
ABAC 的策略引擎实现起来会复杂一些:
// ABAC 策略评估伪代码
public class AbacPolicyEngine {
public boolean evaluate(Subject subject, Resource resource, Action action, Environment env) {
// 加载所有匹配的策略
List<Policy> policies = loadPolicies(subject, resource, action);
for (Policy policy : policies) {
// 逐一评估策略中的条件
boolean subjectMatch = matchSubject(policy.getSubjectRules(), subject);
boolean resourceMatch = matchResource(policy.getResourceRules(), resource);
boolean envMatch = matchEnvironment(policy.getEnvironmentRules(), env);
if (subjectMatch && resourceMatch && envMatch) {
return policy.getEffect() == Effect.ALLOW;
}
}
return false; // 默认拒绝
}
}
我曾经踩过的坑:ABAC 虽然灵活,但策略数量一多,性能就会急剧下降。有一次我在接口适配层用了 ABAC,结果每次请求都要评估 50 多条策略,接口响应时间从 5ms 飙升到 200ms。后来加了策略缓存和预编译,才把性能拉回来。
3.3 PBAC:基于策略的访问控制
PBAC 可以理解为 ABAC 的升级版。它把授权逻辑完全抽象成「策略」,策略可以动态加载、热更新,甚至支持策略的组合与优先级。
PBAC 的核心特点是:
- 策略与代码分离:策略写在配置文件或数据库中,不用改代码
- 支持策略组合:允许多条策略叠加,按优先级裁决
- 运行时热更新:策略变更后,不用重启服务
一个典型的 PBAC 策略配置:
{
"policies": [
{
"id": "policy-001",
"name": "销售部查看客户数据",
"priority": 10,
"effect": "allow",
"conditions": {
"subject.department": "sales",
"resource.type": "customer_data",
"resource.sensitivity": {"lte": "confidential"},
"env.time": {"between": ["09:00", "18:00"]}
}
},
{
"id": "policy-002",
"name": "全局拒绝夜间访问",
"priority": 100,
"effect": "deny",
"conditions": {
"env.time": {"between": ["22:00", "06:00"]}
}
}
]
}
注意:PBAC 的策略优先级很重要。上面的例子中,policy-002 优先级更高(100 > 10),所以即使销售部满足 policy-001 的条件,如果在夜间访问,最终结果还是拒绝。
3.4 三种模型对比
我把三种模型的核心差异整理成了表格,方便你对比:
| 维度 | RBAC | ABAC | PBAC |
|---|---|---|---|
| 粒度 | 粗粒度(角色级) | 细粒度(属性级) | 细粒度(策略级) |
| 灵活性 | 低(角色固定) | 高(属性组合) | 极高(策略热更新) |
| 性能 | 高(简单查表) | 中(需评估条件) | 中低(策略解析开销) |
| 维护成本 | 低 | 中 | 高(需策略管理平台) |
| 适用场景 | 角色稳定的内部系统 | 多维度权限控制 | 动态变化的复杂权限 |
3.5 接口适配中的选型策略
在接口适配场景下,选型不能只看模型本身,还得考虑适配层的特殊性。我个人习惯按这几个维度来决策:
- 接口数量:少于 50 个接口,RBAC 够用;超过 200 个,考虑 ABAC 或 PBAC
- 权限变化频率:每周变更少于 5 次,RBAC;频繁变更,上 PBAC
- 性能要求:要求 P99 延迟 < 10ms,优先 RBAC;可以接受 50ms 以内,ABAC 或 PBAC
- 团队规模:小团队(< 10 人),RBAC 最省心;大团队需要权限管理平台,PBAC 更合适
我的建议:如果你刚开始做接口适配,从 RBAC 起步准没错。等发现角色膨胀到难以维护时,再逐步引入 ABAC 或 PBAC。别一上来就搞复杂的策略引擎——你想想看,万一策略写错了,整个适配层的权限就全乱了。
3.6 三种模型的选型决策流程
下面这张图是我在实际项目中总结的选型决策流程,帮你快速判断该用哪种模型:
3.7 避坑指南
最后分享几个我亲身踩过的坑:
我曾经犯过的错:
- 角色膨胀:在一个 CRM 系统里,我一开始只设计了 5 个角色,半年后膨胀到 47 个。每个角色对应一组权限,维护起来简直噩梦。后来重构时引入了 ABAC,用部门+职级+数据范围三个属性替代了 40 多个角色。
- 策略冲突:PBAC 的策略多了以后,很容易出现「允许」和「拒绝」同时匹配的情况。我后来强制要求每条策略必须有优先级,并且默认拒绝,才解决了这个问题。
- 性能陷阱:ABAC 在接口适配层做权限校验时,如果每次请求都去数据库查策略,性能会非常差。我的解决方案是:策略预加载到本地缓存 + 策略表达式预编译 + 热点策略走硬编码。
嗯,授权模型这块就讲这么多。记住一句话:没有最好的模型,只有最适合你场景的模型。RBAC 简单可靠,ABAC 灵活强大,PBAC 动态可控——选哪个,取决于你的接口适配层到底需要多细的权限控制。