← 所有文章
对比选型

Telegram Webhook secret_token 与 HMAC:接收端到底该验证什么

Telegram Bot API 的 secret_token 不是 HMAC 签名。通过 setWebhook 配置后,Telegram 会把同一个值放入 X-Telegram-Bot-Api-Secret-Token 请求头,接收端将它与本地配置的令牌比较。UnifyPort 则使用另一种契约:启用签名后,需要用时间戳与原始请求体计算 HMAC-SHA256,再验证 X-Device-Signature。这两套检查不能互换。

先记住这几个区别

  • Telegram 的密钥请求头直接携带共享凭证,不是根据 JSON 正文计算出的摘要。
  • UnifyPort 签名通过端点的 signing_secret,绑定原始请求体与 X-Device-Timestamp
  • 两种接收端都需要 HTTPS、密钥保护和幂等处理。
  • 应根据可信的路由配置选择验证方式,不能相信尚未验证的 JSON provider 字段,也不能看哪个请求头存在就用哪种方式。

本文只讨论请求验证。如果你还没决定使用机器人还是既有消息账号,先看 Telegram Bot API webhook 与统一入站 webhook 对比

Telegram secret_token 实际验证什么

Telegram 官方 Bot API 文档secret_token 定义为 setWebhook 的可选参数:长度为 1–256 个字符,只允许 A-Za-z0-9_-。配置后,每次 webhook 请求都会在 X-Telegram-Bot-Api-Secret-Token 中携带该值。

如果接收端要求这项保护,缺失或不匹配的请求头就不能进入可信处理队列。完全匹配说明请求方持有配置的值,但并没有建立这个值与请求正文之间的独立密码学关联。

这一点在代理或转发服务处尤其重要:能够读取令牌的组件,也能携带同一令牌提交不同正文。HTTPS 保护传输连接;静态请求头本身无法检测 TLS 终止后发生的正文变化。这是在划分信任边界,不是说官方 Bot API 不适合使用。

建议为 webhook 单独生成凭证,不要复用 bot token,也不要把密钥粘贴到公开抓包服务。访问日志、链路追踪导出和排障截图都应对它脱敏。

静态令牌与正文签名的对照

HMAC 是基于共享密钥的消息认证机制。按照 UnifyPort 文档,接收端需要重新计算指定输入的摘要,而不是把签名请求头与密钥直接比较。

问题Telegram Bot API webhook已启用签名的 UnifyPort webhook
配置项setWebhook.secret_token端点的 signing_secret
验证请求头X-Telegram-Bot-Api-Secret-TokenX-Device-Signature
收到的值配置的令牌本身十六进制 HMAC-SHA256 摘要
是否覆盖正文是,使用原始字节
是否覆盖时间戳是,X-Device-Timestamp
接收端操作比较请求头与令牌重新计算并比较摘要
是否保证只处理一次

UnifyPort 的签名输入严格为:

<X-Device-Timestamp>.<raw request body>

时间戳使用 RFC 3339 UTC 格式,中间是一个字面量点号。格式化 JSON、改变空白字符,或者先解析再序列化,都可能改变签名字节。signing_secret 是 HMAC 密钥,不是请求头应直接等于的值。

signing_secret 为空,UnifyPort 会关闭签名,不发送 X-Device-Signature。要求签名的接收端应拒绝这种请求,而不是自动切换到别的验证模式。

为两类请求保留独立入口

建议为原生 Telegram 更新与 UnifyPort 事件分别设置应用路由。这里说的是你的应用设计,不是新增的平台 API endpoint。面向东南亚的跨境团队即使把 Telegram、LINE 和 WhatsApp 放进同一个业务队列,也应先在入口完成各自的验证。

  1. 绑定来源与凭证。 在部署配置中明确每条路由接受哪种验证机制。
  2. 先验证再分发。 Telegram 校验令牌请求头;已签名的 UnifyPort 请求校验原始正文 HMAC 和时间戳新鲜度。
  3. 按各自结构校验负载。 不要把原生 Telegram Update 交给期待 UnifyPort message.received 的处理器。
  4. 持久化已接受的任务。 请求认证、幂等与业务授权分别处理。
  5. 记录失败类型而非密钥。 排障日志只说明哪项检查失败,不输出敏感请求头。

不要使用“任一请求头通过即可”的共享中间件。否则,较弱或被意外启用的分支就会成为另一条通过验证的路径。尤其不能让 Telegram 令牌代替 UnifyPort 路由所要求的 HMAC。

第二套契约的实现细节可参考 HMAC 防重放与重试处理。消息 JSON 中的时间字段,不能代替受投递签名保护的时间戳。

上线前应测试哪些边界

以下是建议的测试,不是已经执行的测试结果。请在隔离环境中使用自己控制的凭证验证。

测试接收端预期行为
Telegram 请求头缺失或错误在可信处理前拒绝
Telegram 令牌正确,但正文改变单靠令牌检查无法发现;仍需负载校验与可信传输边界
UnifyPort 正文在签名后改变摘要不匹配,拒绝
UnifyPort 签名有效,但时间戳超出配置窗口按新鲜度策略拒绝
将 Telegram 令牌发送到 UnifyPort 路由拒绝,不切换验证机制
同一真实普通事件再次投递幂等接受,不重复执行业务动作

新鲜度窗口应结合时钟精度和投递条件制定,不要照搬其他平台的值。请求通过验证,也不意味着可以执行消息里要求的任何业务操作。

UnifyPort 的适用边界

UnifyPort 非官方接口为已连接的消息账号提供标准化事件。HMAC 保护的是 UnifyPort 到你的接收端这一段交接,不是 Telegram 原生签名,也不是 Telegram 用户端到端作者身份的证明。

如果产品本来就是 Telegram 机器人,在该入口实现 Telegram 文档中的保护即可,不必仅为改变验证机制而迁移平台。如果通过 UnifyPort 接入账号级或跨渠道队列,就应遵循它的独立契约,并在创建 webhook 端点时启用签名。

常见问题

应该用 Telegram secret_token 计算 HMAC 吗?

验证官方 Bot API 密钥请求头时不需要。应比较该请求头与配置的令牌,不要为直接携带令牌的请求头自行设计正文签名算法。

可以直接比较 X-Device-Signature 与 signing_secret 吗?

不可以。先对文档规定的“时间戳加原始请求体”计算 HMAC-SHA256,再将结果与收到的十六进制签名比较。

任一种机制能阻止重复处理吗?

不能。认证与去重是两件事。应持久化已接受任务,并让下游操作保持幂等;HMAC 本身不会让投递变成只执行一次。

下一步与来源

开发 UnifyPort 接收端时,以 webhook 投递与签名文档作为实现契约。

来源核对日期:2026-09-17。

UnifyPort API

让消息接入变成一条稳定的产品管线。

先用统一 API 跑通发送,再用标准事件把所有入站消息接回业务系统。