Webhook 安全
Webhook 同时包含两种方向:调用平台 Webhook 发送通知,以及接收平台事件回调。前者的完整 URL 往往就是发送凭据,后者必须验证来源、防止重放并快速确认。
| 方向 | 主要风险 | 必须控制 |
|---|---|---|
| 出站通知 | URL 泄露、误发、限流、重复发送 | 服务端保存、最小目标、超时、业务码、有限重试 |
| 入站回调 | 伪造请求、重放、超大请求、慢处理 | HTTPS、验签、大小限制、事件去重、快速确认 |
浏览器端不应直接调用通知 Webhook。除了凭据暴露,跨域策略、扩展程序、错误采集和访问日志都会扩大泄露面。
签名与重放防护
Section titled “签名与重放防护”严格使用平台规定的原始请求体、字段顺序、时间戳单位、编码和摘要算法。解析 JSON 后重新序列化可能改变空白和字段顺序,导致入站签名失败。
- 校验时间戳允许窗口,拒绝过期或明显来自未来的请求。
- 使用常量时间比较签名,避免普通字符串比较泄露时序信息。
- 以事件 ID 建持久化唯一键;没有事件 ID 时使用平台规定的稳定字段组合。
- 签名验证成功不等于事件没有处理过,验签和事件去重必须同时存在。
通用实现原则见签名验证标准,具体拼接算法仍以每个平台教程和官方资料为准。
出站请求控制
Section titled “出站请求控制”发送端设置连接、响应和整体请求超时。只接受 HTTPS 官方域名,用户可配置 URL 时使用域名允许列表并阻止内网、环回和云元数据地址,避免 SSRF。
调用后同时检查 HTTP 状态和平台业务码。Webhook 返回 2xx 但业务码失败时不能记为成功;平台返回消息 ID 或任务 ID 时应保存用于后续查询。
- 网络超时、
429和明确的临时5xx可以有限重试。 400、401、403、签名错误和目标无效不能自动重试。- 优先使用平台提供的
uuid、幂等键或任务查询接口。 - 没有平台幂等能力时,在业务侧保存事件 ID、目标和内容摘要,阻止重复发送。
- 采用指数退避和随机抖动,设置最大次数与最长总时长。
429优先读取Retry-After、retry_after或平台业务字段。
Webhook 回调入口应在平台时限内完成验签、落去重记录并返回确认。模型调用、文件下载和业务查询放到队列或后台任务,避免平台因超时反复投递。
IP 白名单限制的是调用来源,不是凭据替代品。多节点、NAT、Serverless 或代理环境需要确认真实公网出口;出口变化后同步更新平台配置。入站回调可配合 WAF 和速率限制,但不能只信任来源 IP,因为平台地址可能变化。
权限按机器人、应用和环境隔离。测试 Webhook 不能指向生产群,生产凭据不能注入 Preview 构建或 Fork PR。
可以记录:平台、环境、应用别名、目标类型、请求 ID、业务码、重试次数、耗时和消息大小。
不得记录:完整 URL、Authorization、Secret、Token、签名原文、解密密钥、用户隐私数据和完整消息正文。HTTP 客户端异常可能自动包含 URL 与 Header,应在统一错误层脱敏后再输出。
- HTTPS、证书续期、DNS 和出口网络已在部署环境验证。
- 签名正确、错误签名、过期时间戳和重复事件均有测试。
- 请求体大小、输入长度、并发和每日预算有限制。
- 重试只覆盖可恢复错误,并且有幂等保护。
- 凭据轮换、泄露撤销和平台停用路径已记录。
- 监控能区分网络、HTTP、平台业务和目标端失败。