AuthoritySlot是 Sentinel 中用于实现 黑白名单授权控制(Authority Control) 的核心组件。它通过拦截请求上下文中的 origin(调用来源),与配置的规则进行匹配,从而决定是否放行请求。
我们从整体架构出发,逐层拆解理解:
一、整体目标
根据请求来源(origin)是否在白名单或黑名单中,决定是否允许访问某个资源。
- 白名单模式(AUTHORITY_WHITE):只有来自指定 origin 的请求才被允许。
- 黑名单模式(AUTHORITY_BLACK):来自指定 origin 的请求被拒绝。
典型应用场景:
- 微服务 A 只允许被 B 和 C 调用,拒绝其他服务;
- 防止恶意调用方(如已知的攻击 IP 或服务名)访问敏感接口。
二、组件结构概览
| 类 | 职责 |
|---|---|
AuthoritySlot |
Sentinel 处理链中的一个插槽(ProcessorSlot),负责在请求进入时执行权限检查 |
AuthorityRuleManager |
管理所有 AuthorityRule 规则的加载、更新、存储 |
AuthorityRuleChecker |
核心判断逻辑:给定一条规则和当前上下文,是否通过 |
AuthorityRule |
权限规则实体:包含资源名、限制应用(limitApp)、策略(黑白名单) |
三、详细解析
1. AuthoritySlot ------ 拦截入口
java
public void entry(...) throws Throwable {
checkBlackWhiteAuthority(resourceWrapper, context);
fireEntry(...); // 继续处理链
}
- 在每次请求进入 Sentinel 保护的资源时,该 Slot 会被调用。
- 调用
checkBlackWhiteAuthority进行权限校验。 - 如果校验失败(抛出
AuthorityException),后续逻辑不会执行(即请求被拒绝)。
✅ 这是典型的 责任链模式(Chain of Responsibility) 中的一环。
2. AuthorityRuleManager ------ 规则管理中心
关键点:
- 使用
RuleManager<AuthorityRule>存储规则,按 resource 名 分组。 - 支持动态规则更新(通过
SentinelProperty+PropertyListener机制)。 - 提供
getRules(String resource)方法,快速获取某资源的所有权限规则。
规则加载逻辑(loadAuthorityConf):
java
for (AuthorityRule rule : list) {
if (!isValidRule(rule)) continue;
if (StringUtil.isBlank(rule.getLimitApp())) {
rule.setLimitApp(RuleConstant.LIMIT_APP_DEFAULT); // 默认值 ""
}
String resource = rule.getResource();
// 每个 resource 最多只保留一条 AuthorityRule!
if (newRuleMap.containsKey(resource)) {
warn("Ignoring redundant rule");
} else {
newRuleMap.put(resource, [rule]);
}
}
⚠️ 重要限制 :每个资源只能有一条 AuthorityRule 。
这意味着你不能为同一个 API 同时配置"拒绝 A"和"只允许 B"------必须合并成一条规则(比如 limitApp="A,B" + 黑名单策略)。
3. AuthorityRuleChecker.passCheck() ------ 核心判断逻辑
java
static boolean passCheck(AuthorityRule rule, Context context) {
String requester = context.getOrigin(); // 调用方标识,如 "service-A"
String limitApp = rule.getLimitApp(); // 配置的限制应用列表,如 "app1,app2"
// origin 为空 或 limitApp 为空 → 放行(安全默认)
if (isEmpty(requester) || isEmpty(limitApp)) {
return true;
}
// 初步判断:limitApp 字符串是否包含 requester(子串匹配)
boolean contain = limitApp.indexOf(requester) > -1;
// 但必须是 **精确匹配**(按逗号分割后逐个比对)
if (contain) {
boolean exactlyMatch = false;
for (String app : limitApp.split(",")) {
if (requester.equals(app.trim())) { // 注意 trim()
exactlyMatch = true;
break;
}
}
contain = exactlyMatch;
}
// 根据策略判断
if (rule.getStrategy() == AUTHORITY_BLACK && contain) {
return false; // 黑名单命中 → 拒绝
}
if (rule.getStrategy() == AUTHORITY_WHITE && !contain) {
return false; // 白名单未命中 → 拒绝
}
return true;
}
举个例子:
| 场景 | limitApp | strategy | origin | 结果 |
|---|---|---|---|---|
| 白名单 | "web,admin" | WHITE | "admin" | ✅ 通过 |
| 白名单 | "web,admin" | WHITE | "hacker" | ❌ 拒绝 |
| 黑名单 | "bad,bad2" | BLACK | "bad" | ❌ 拒绝 |
| 黑名单 | "bad,bad2" | BLACK | "good" | ✅ 通过 |
| origin 为空 | 任意 | 任意 | "" | ✅ 通过(安全宽松) |
🔍 为什么先用
indexOf再精确匹配?是一种性能优化:先快速排除明显不包含的情况,再做 split 和遍历。
4. AuthorityRule ------ 规则定义
resource:受保护的资源名(如 "/api/order")limitApp:逗号分隔的调用方列表(如 "service-a,service-b")strategy:0=AUTHORITY_WHITE(白名单)1=AUTHORITY_BLACK(黑名单)
📌 注意:
limitApp中的值必须与Context.getOrigin()返回的值完全一致(区分大小写、无空格)。
四、使用方式(如何生效?)
-
设置 origin
在调用方,需通过
ContextUtil.enter(resourceName, origin)设置 origin:javaContextUtil.enter("my-resource", "payment-service"); -
配置 AuthorityRule
javaAuthorityRule rule = new AuthorityRule() .setResource("my-resource") .setLimitApp("order-service,auth-service") // 允许这两个服务调用 .setStrategy(RuleConstant.AUTHORITY_WHITE); AuthorityRuleManager.loadRules(Collections.singletonList(rule)); -
请求进入时自动校验
Sentinel 的
AuthoritySlot会在处理链中自动拦截并校验。
五、注意事项 & 最佳实践
✅ 优点:
- 简单高效,适合服务间调用鉴权;
- 支持动态规则更新(无需重启);
- 与 Sentinel 其他功能(流控、熔断)无缝集成。
⚠️ 限制/注意:
- 每个资源仅支持一条 AuthorityRule → 设计时需合并规则。
- origin 必须由调用方显式设置,否则为空 → 自动放行(可能造成安全漏洞!)。
- 不适用于 HTTP Header/IP 级别控制 (那是网关/WAF 的事),这里控制的是 逻辑调用方身份(如微服务名)。
- limitApp 不支持通配符或正则(仅精确匹配)。
六、总结
这套机制实现了 基于调用方身份的访问控制,核心思想:
"谁(origin)可以访问什么资源(resource)?"
- 通过
AuthoritySlot插入处理链; - 通过
AuthorityRuleManager管理规则; - 通过
AuthorityRuleChecker执行黑白名单判断; - 规则粒度:每个资源一条规则,支持白名单或黑名单。
非常适合 微服务内部调用鉴权 场景,是 Sentinel 实现"零信任"网络的一个轻量级手段。
如果你有具体使用问题(比如如何设置 origin、如何动态推送规则、为何规则没生效等),欢迎继续提问!