鉴权与前置检查
请求在访问任何 AI 上游之前,会经过全局中间件、API Key 鉴权、权限和计费前置检查。大多数 4xx 错误发生在这一阶段。
全局中间件
不同路由会组合以下能力:
- Recovery:捕获 panic,避免进程退出。
- CORS:控制浏览器跨域。
- Security Headers / CSP:保护管理后台。
- Request Body Limit:防止无界请求体。
- Client Request ID:贯穿日志和错误。
- Ops Error Logger:采集标准化错误。
- Endpoint Normalization:把别名路径映射到统计端点。
模型网关不使用 Web JWT,而使用 API Key middleware。
API Key 从哪里读取
不同客户端使用的 Header 不同,网关兼容常见形式,例如:
Authorization: Bearer sk-...或:
x-api-key: sk-...部署反向代理时不能删除 Authorization、x-api-key 或客户端 metadata 头。
鉴权快照
一次成功鉴权会得到:
- API Key ID、状态、分组和额度。
- 用户 ID、状态、余额、并发和角色。
- 分组平台、倍率和功能开关。
- 当前可用订阅。
- IP ACL 与部分缓存版本。
后续 Handler 不需要重复查这些基础对象。
失败顺序
典型检查顺序:
- Key 是否存在。
- Key 和用户是否 active。
- Key 是否过期。
- 来源 IP 是否通过黑白名单。
- Key 是否已经分配分组。
- 用户是否有权使用分组。
- 分组是否 active。
- 订阅和权益快照是否可用。
错误响应会尽量使用客户端协议期望的格式。Gemini、Anthropic 和 OpenAI 的错误 JSON 不完全相同。
真实 IP 与 ACL
应用默认不应无条件相信转发 IP。生产拓扑应是:
Internet → trusted proxy/CDN → Sub2API只在确认所有请求必经受控代理后,配置 trusted proxies 和转发 IP ACL。否则攻击者可以自己构造 X-Forwarded-For。
验证方式:在代理前后分别发送请求,确认运维日志中的 client IP 与预期一致。
请求体与 JSON
网关有两层请求体限制:
- Server 全局限制,保护 H2C 和所有路由。
- Gateway 限制,保护模型请求解析。
部分 Handler 使用宽容 JSON 读取以兼容客户端,但仍会检查空 body、JSON 合法性、model 和 stream 字段类型。
客户端识别
系统会识别 Claude Code、Codex、Gemini CLI 等客户端,信号可能来自:
- User-Agent。
- 请求路径。
- metadata 和 system prompt 特征。
- 特定请求 Header。
- request body 的协议结构。
客户端识别会影响:
- Claude Code only。
- 最低版本限制。
- Codex metadata 注入。
- 模型 manifest。
- WebSocket/HTTP 路由。
- 特定预热请求拦截。
反向代理不应随意统一改写 User-Agent。
内容审核
在获得上游账号前,Handler 可以调用内容审核:
- 从请求提取文本或可审查输入。
- 根据协议和模型选择审核策略。
- 命中时记录 hash、关键词、用户和 Key。
- 按配置阻断、封禁或仅观察。
审核服务故障时采用 fail-open 还是 fail-closed 取决于配置。生产环境要明确选择,不能依赖默认直觉。
用户并发
用户槽位在余额检查之前获取。达到上限时:
- 非流式请求等待或返回并发错误。
- 流式请求在等待期间可以输出 keepalive。
- 等待队列也有最大人数和超时。
- 客户端断开会通过 context 释放等待和槽位。
等待成功后会重新检查权益,避免排队期间余额发生变化。
Billing Preflight
前置检查只判断“有资格开始”,不会精确预测最终费用。顺序可能涉及:
- 有效订阅和窗口额度。
- 用户余额与 minimum reserve。
- API Key quota 和费用窗口。
- 用户平台配额。
- Billing cache circuit breaker。
计费基础设施不可用时,标准模式倾向返回服务不可用,而不是免费放行。
分组功能门禁
即使鉴权和余额通过,请求仍可能因为分组规则被拒绝:
- Claude Code only。
- Messages dispatch 未开启。
- 图片/批量图片/视频未开启。
- Embeddings 平台不支持。
- 模型不在 scope 或 whitelist。
- 账号类型要求 OAuth only。
前置检查排障
| 错误 | 检查位置 |
|---|---|
| invalid API key | Key 值、缓存、软删除 |
| user disabled | 用户状态 |
| group required | Key 未绑定分组 |
| permission denied | 用户分组权限、客户端门禁 |
| quota exceeded | Key、订阅、平台窗口 |
| billing unavailable | Redis/DB、circuit breaker |
| request too large | CDN、代理、server、gateway 四层限制 |
| invalid request | JSON、model、stream、协议字段 |
在请求尚未访问上游时,不要通过更换账号来解决这些错误。