消费者与鉴权
今天看"谁能访问我的 API"这套鉴权。核心发现:所谓"消费者"其实就是 key-auth 插件的一个全局实例,"给路由加鉴权"就是往 allow list 里加名字。理解这层映射,鉴权就不神秘了。
消费者是什么
Authorization: Bearer sk-abc123 打到路由 order-api → 网关查 key-auth 的 keys 是否有 sk-abc123,再查这条路由的 allow list 是否放行对应消费者 → 命中则放行,否则返回 401。消费者(Consumer)代表"一个 API 调用方",带一份凭据(API Key)。给某条路由配上"只允许消费者 A、B 访问",未带正确 Key 的请求就被拦。
ConsumersController
ConsumersController.java(/v1/consumers,:45-49):list(:58)、add(:67,validate(false) 凭据值必填)、query(:78)、put(:88,validate(true) 凭据值可空)、delete(:105)。
validate(false) 表示"凭据值必须填"(新建就要给 Key);put 时 validate(true) 表示"凭据值可以空"(改其他字段时不强制重填 Key)。同一个校验方法用一个布尔参数区分新建/更新的宽严——小技巧。存进 key-auth 全局实例
ConsumerServiceImpl.addOrUpdate(:64-79):取/建 key-auth 插件的全局实例(setInternal(true) + setGlobalTarget + initDefaultGlobalConfigs)→ handler.saveConsumer → addOrUpdateAll。
key-auth 这个鉴权插件的全局实例配置里(它的 consumers 数组)。因为消费者本来就是给 key-auth 插件用的数据,直接存进插件配置最自然。Console 的一切都落成插件/CRD/ConfigMap——消费者也不例外。凭据 → 插件配置
KeyAuthCredentialHandler.saveConsumer(:125-212)是"凭据 → 插件配置"映射核心,按 KeyAuthCredentialSource 写 in_header / in_query:
- BEARER:key 固定
Authorization,值加Bearer前缀(:188-195) - HEADER:自定义请求头
- QUERY:查询参数
写 keys/credentials,强制 global_auth=false(:210);不同消费者用相同 key 值会报错(:165-168)。
global_auth=false 表示"不是全局强制鉴权"——具体哪条路由要鉴权由 allow list 决定(下一讲)。目前只支持 API Key
ConsumerServiceImpl 的 Handler 注册表(:51-56)只注册了 KeyAuthCredentialHandler。jwt-auth 只有插件名常量(BuiltInPluginName.java:40)没有对应 Handler。凭据类型 CredentialType.java 唯一值就是 key-auth。
CredentialHandler 实现,注册进 ConsumerServiceImpl.java:51-56 的表里即可。这又是一个绝佳的"动手改进"练习。allow list 机制
"某路由允许哪些消费者"用 allow list 表达。ConsumerServiceImpl:
listAllowLists(:120-155)/getAllowList(:157-192,禁 GLOBAL)updateAllowList(:194-278):空 credentialTypes 默认 KEY_AUTH,按 ADD/REMOVE/REPLACE/TOGGLE_ONLY 改 allow
allow 数组——列出这条路由放行哪些消费者,加上 enabled(是否开启鉴权)。四种操作:ADD 加人、REMOVE 移人、REPLACE 整体替换、TOGGLE_ONLY 只切换开关不改名单。前端"给路由勾选允许的消费者"就调这个。路由鉴权桥梁
RouteServiceImpl.add。路由本身先转成 Ingress 写下去;接着你被交给 writeAuthConfigResources——它把你携带的 RouteAuthConfig 翻译成一次 AllowList 的 REPLACE 操作,落到那条路由对应的 ROUTE 作用域 key-auth 实例的 allow 数组里。于是"路由"和"鉴权"两个模块,就靠这一步接上了。下次读取时 ingress2Route 再把 allow 反向回填成 authConfig 给前端展示。回到 Day 10 的悬念——为什么 RouteServiceImpl.add 要 writeAuthConfigResources?答案在 RouteServiceImpl.java:
- add/update 后
writeAuthConfigResources(:167-175):把路由的RouteAuthConfig转成 AllowList,用 REPLACE 写入。 - 读取时
ingress2Route回填RouteAuthConfig。 - delete 时清 ROUTE 作用域的 key-auth 实例(
:156-165)。
authConfig(Day 09 见过的字段)就是这层桥梁的载体。今日小结 + 动手
🧠 今天你应该能回答
- 消费者是什么?它存在哪(不是数据库)?
- 三种凭据 source(BEARER/HEADER/QUERY)的区别?
- 目前支持几种鉴权?加 JWT 的扩展点在哪?
- allow list 的四种操作?路由鉴权和 key-auth 实例怎么对应?
✋ 动手
cd /Users/bitmart/work/codes/github/higress-group/higress-console/backend/sdk/src/main/java/com/alibaba/higress/sdk
sed -n '51,79p' service/consumer/ConsumerServiceImpl.java
sed -n '125,212p' service/consumer/KeyAuthCredentialHandler.java
sed -n '194,278p' service/consumer/ConsumerServiceImpl.java
sed -n '156,175p' service/RouteServiceImpl.java