访问控制设计
访问控制回答「谁能调什么」。网关用三层控制点组合:访问密钥(身份)→ 密钥组(模型/LB 授权)→ Header ACL(请求头规则)。
三层控制点
| 层 | 管什么 | 配置处 |
|---|---|---|
| 访问密钥 | 调用方身份 | 控制台 → 访问密钥 |
| 密钥组 | 模型可达 + LB 可达 | 控制台 → 密钥组(models + load_balancers) |
| Header ACL | 按请求头匹配放行/拒绝 | 控制台 → Header ACL 规则 |
白名单模式(默认拒绝 + 单条放行)
正则引擎不支持 lookahead,「值不含 X 才放行」写不成单条正则。需要默认拒绝、只放行特定请求时,反过来编排:
default_action设为deny(默认拒绝)。- 用一条「含 X 则
allow」的规则放行匹配项。 - 或拆成多条规则覆盖各放行条件。
这种「白名单 + 显式放行」比黑名单更安全——新增的未知请求默认被拒。配置示例见 配 Header ACL 的白名单模式。
作用域与优先级
Header ACL 规则有三级作用域:全局 → 密钥组 → 访问密钥。匹配时 first-match-wins,更具体的作用域优先。字段见 Header ACL 规则字段。
表达力边界与规则编排
正则不支持 lookahead / 回溯引用
正则引擎为线性时间实现、抗 ReDoS,故不支持 lookahead((?=...) / (?!...))与回溯引用(\1)。代价是「值不含 X 才放行」这类否定条件无法用单条正则表达——改用上面的白名单模式(默认 deny + 显式 allow)。
规则加载失败(语法错等)时被跳过并记录告警,其余规则照常生效——所以规则要测过再上,且关键放行规则别只靠一条可能加载失败的。
密钥组:两个独立维度
密钥组的 models 与 load_balancers 是两个独立列表:
models: ["*"](所有模型)不附带 LB 权限。load_balancers: ["*"]也不附带普通模型权限。- 两个维度要分别勾选。
且 LB 是授权单元——放行某 LB 后,该组密钥能到达该 LB 的每一个 entry,不再用 models 逐个校验。严格隔离时别用 LB,见 多租户隔离。
规则失效时的行为
- 规则语法错:加载时被忽略,记告警,其余规则生效。
- 正则不匹配:按
default_action走。 - 多作用域:first-match-wins,具体作用域优先。
常见问题
Q:密钥组 models 写别名行吗? 不行。只匹配规范名称(name 字段),不解析别名。见 上游与模型字段 的「模型别名与隐藏名称」。
Q:hide_name 的模型怎么授权? 密钥组 models 写它的规范名(不是别名)。hide_name=true 只影响客户端能否用规范名访问,授权仍按规范名。见 上游与模型字段。
Q:怎么按租户限流? 每租户独立访问密钥,限流按密钥计。多实例配 Redis 让限流跨实例共享。见 多租户隔离。
下一步:多租户隔离 看隔离;Header ACL 规则字段 看字段;配 Header ACL 看示例。
