增加非白名单的日志
This commit is contained in:
1 parent
7f4adad7b1
commit
06bb066d82
7 files changed
+332
-28
No files matched your search
@@ -2,8 +2,8 @@
|
||||
|
||||
| 项 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | Implemented |
|
||||
| 日期 | 2026-09-05 |
|
||||
| 状态 | Implemented;已增加拒绝请求的 Origin 诊断日志 |
|
||||
| 日期 | 2026-09-07 |
|
||||
| 负责人 | fire-safety-ymd 后端 |
|
||||
| 需求来源 | 复用既有客户端的 `/api/v1/apps/{app_id}/completion`、`xtoken` 与 `event: result` 契约 |
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
| `FIRE_SAFETY_CHAT_COMPAT_APP_ID` | 空 | 非空时注册兼容路径;1 至 128 个 ASCII 字母、数字、下划线或连字符 |
|
||||
| `FIRE_SAFETY_CHAT_AUTH_TOKEN` | 空 | 兼容路径期望的 `xtoken`;默认至少 32 个可打印 ASCII 字符,兼容开关开启时允许已交付的旧短凭证 |
|
||||
| `FIRE_SAFETY_CHAT_ALLOW_LEGACY_SHORT_TOKEN` | `false` | 仅为已交付旧客户端短凭证的受控测试/迁移临时兼容开关;新环境不得开启 |
|
||||
| `FIRE_SAFETY_CHAT_ALLOWED_ORIGINS` | 空 | 逗号分隔的精确 HTTP(S) 浏览器 Origin;不允许 `*`、非根路径、查询或片段;单个末尾 `/` 会被规范化移除 |
|
||||
|
||||
兼容路径只有在 `FIRE_SAFETY_CHAT_ENABLED=true` 且 App ID 非空时注册。App ID 是用于路径匹配的公开标识,不是 Secret;不匹配的路径返回 404。
|
||||
|
||||
@@ -120,15 +121,34 @@ SSE 开始前使用 HTTP 状态和 DashScope 风格安全 JSON:
|
||||
SSE 开始后的失败发送 `event: error`,只包含稳定 code、通用 message、request ID 和本地 session ID;不发送 `finish_reason: "stop"`,也不返回任何已接收的部分回答。
|
||||
|
||||
沿用原生 Chat 的主要状态:400 输入错误、401 token 错误、403 Origin 错误、404 App/会话不存在、409 会话忙、503 容量不足,以及 502/504 上游失败或超时。
|
||||
兼容入口的 403 响应仍只返回稳定错误 JSON;服务端日志在拒绝时提供有限诊断信息,便于确认发送方应加入哪一个精确 Origin,
|
||||
但不会因为诊断而放宽鉴权或预检规则。
|
||||
|
||||
## 8. CORS、Nginx 与 Secret
|
||||
|
||||
- 浏览器 Origin 必须精确出现在 `FIRE_SAFETY_CHAT_ALLOWED_ORIGINS`;不允许 `*` 或 credentials。
|
||||
- 浏览器 Origin 必须精确出现在 `FIRE_SAFETY_CHAT_ALLOWED_ORIGINS`;多个值用英文逗号分隔,不允许 `*` 或 credentials。
|
||||
- 白名单值的规范形式是 `scheme://host[:port]`,不能带非根路径、查询或片段;单个末尾 `/` 会被接受并规范化移除,配置时建议省略。不要把 API URL、Nginx 上游地址或 Token 当作 Origin。
|
||||
- 预检只允许 `POST` 以及 `Content-Type`、`xtoken`、`X-DashScope-SSE`、`X-Request-ID`。
|
||||
- Nginx 示例只公开精确兼容路径、`/mcp` 和可选 `/health`,其余路径返回 404。
|
||||
- Nginx 不比较或注入 `xtoken`、SuperAgent Open API Key、MCP Bearer 或数据库凭证;Header 原样交给 Go 验证。
|
||||
- 对话 SSE 必须关闭代理缓冲、缓存、gzip 和上游自动重试,并让代理超时覆盖 Chat 总运行时限。
|
||||
|
||||
### 8.1 403 Origin 诊断日志
|
||||
|
||||
兼容入口只在拒绝场景记录诊断字段:普通 POST 的非空 Origin 不在白名单时记录
|
||||
`result=forbidden_origin` 与 `origin`;CORS 预检拒绝时记录 `result=preflight_forbidden`、
|
||||
`origin`、`preflight_method`、`preflight_headers` 和稳定 `reason`。`reason` 取值为
|
||||
`origin_missing`、`origin_not_allowed`、`method_not_allowed` 或 `headers_not_allowed`。
|
||||
|
||||
每个请求 Header 最多保留前 256 个输入字节,超长值追加 `[truncated]` 后再引用/ASCII 转义,
|
||||
以确保恶意换行不能伪造日志记录。成功请求不记录 Origin。日志禁止记录 `xtoken`、`Authorization`、`Cookie`、
|
||||
prompt/body、会话 ID、Provider Session、Provider payload 或其他 Secret。
|
||||
|
||||
运维人员只能把日志中的完整 `origin` 当作排障线索,不能直接执行或无审查复制;若出现 `[truncated]`,应从浏览器
|
||||
Network 面板确认完整 Origin。确认后再把 `scheme://host[:port]` 原样加入
|
||||
`FIRE_SAFETY_CHAT_ALLOWED_ORIGINS`,多个来源用英文逗号分隔;禁止 `*`。修改代码需要重新 build 并 recreate,
|
||||
仅修改环境配置也需要 recreate,单独 restart 不会让运行容器读取新值。
|
||||
|
||||
## 9. 验收标准
|
||||
|
||||
- Given App ID 未配置,When 请求兼容路径,Then 路由返回 404,原生 `/api/chat` 行为不变。
|
||||
@@ -139,6 +159,9 @@ SSE 开始后的失败发送 `event: error`,只包含稳定 code、通用 mess
|
||||
- Given 后续请求携带成功返回的 `session_id`,When 调用,Then 复用同一服务端会话映射。
|
||||
- Given Provider 流失败,When SSE 已开始,Then 收到安全 `error`,不收到部分正文或 `stop`。
|
||||
- Given Nginx 配置生效,When 请求未列出的路径,Then 不会转发到 Go 或外部 DashScope。
|
||||
- Given 普通请求的 Origin 不在白名单,When 兼容入口返回 403,Then 日志记录有界、引用/转义后的 `origin`,但不记录 Token、Cookie、prompt/body、会话或 Provider 数据。
|
||||
- Given CORS 预检因来源、方法或请求头名称集合被拒绝,When 返回 403,Then 日志记录有界、引用/转义后的 `origin`、`preflight_method`、`preflight_headers` 和稳定 `reason`,且恶意换行不能增加日志行数。
|
||||
- Given Origin 白名单值被更新,When 服务重新加载配置,Then 精确 `scheme://host[:port]` 值生效,单个末尾 `/` 被规范化移除,而 `*`、非根路径、查询和片段不得被接受。
|
||||
|
||||
## 10. 协议来源
|
||||
|
||||
|
||||
Reference in new issue
Block a user