跳转到内容

签名验证标准

不同平台的签名串拼接顺序、摘要算法、Base64 和 URL 编码规则并不通用。实现时必须逐字段遵循对应平台官方文档,不能把飞书、钉钉、Slack 或企业微信的算法互相替换。

推荐处理顺序:

  1. 限制请求体大小和 HTTP 方法。
  2. 保存原始请求体字节,不先解析再序列化。
  3. 读取平台规定的时间戳、随机数、签名或密文头。
  4. 拒绝超过允许时间窗口的请求。
  5. 按平台规定生成期望签名,并使用常量时间比较。
  6. 以事件 ID 或“时间戳 + 随机数 + 摘要”建立短期重放记录。
  7. 验证成功后再解密、解析和执行业务。

调用群机器人时,签名通常由当前时间戳和机器人 Secret 生成,并随请求参数或请求体发送。服务器时间偏差、毫秒和秒混用、换行符不一致、Base64 后漏做 URL 编码,是最常见的失败原因。

先使用固定时间戳和固定 Secret 建立官方示例测试向量,再接入系统时钟。签名失败不能无限重试,因为同一错误参数不会自行恢复。

  • 服务端启用可靠的时间同步并监控时钟偏差。
  • 接受窗口以平台规定为准,不自行扩大到数小时。
  • 重放记录的过期时间至少覆盖接受窗口。
  • 事件去重和签名防重放是两层控制:签名证明请求来源,事件 ID 防止已通过验证的事件被重复执行业务。

平台支持双密钥时采用重叠窗口:新密钥先发布到验证端,再切换平台配置,最后撤销旧密钥。只支持单密钥时应准备短暂维护窗口,并在切换前暂停非必要重试。日志只记录密钥版本,不记录密钥值或完整签名材料。

  • 正确签名请求通过。
  • 请求体改变一个字节后失败。
  • 时间戳过期或来自未来时失败。
  • 同一事件重复到达时只执行业务一次。
  • 密钥错误时返回明确的客户端错误,不进入重试队列。
  • 日志和错误响应不包含 Secret、Token、完整 Webhook 或解密后的敏感内容。