Skip to content
bitzorcas
中EN

Concept

Webhooks 开放平台架构概览:事件订阅、HMAC 验签与指数退避重试

深入解析 BitzOrcas.Modern Webhooks 开放平台体系,掌握 WebhookSubscription 订阅聚合、HMAC-SHA256 签名加密、死信队列(DLQ)与指数退避重试调度。

Last updated

在面向第三方开放生态的 B2B 平台中,Webhooks 是对外输出业务变更事件的核心通道:

  • 网络超时与接收端宕机(Receiver Outage):外部开发者的服务器发生故障时,平台不能无限重试导致自身线程池耗尽,也不能直接丢弃事件导致数据脱节;
  • 数据伪造与防篡改(Signature Verification):必须提供强密码学签名的 X-Signature-SHA256 请求头,确保接收方能够精准防范中间人攻击;
  • 防范内网 SSRF 攻击:严禁第三方用户将 Webhook URL 指向 http://127.0.0.1 或 http://192.168.0.1 探测内部网络!

BitzOrcas.Modern Webhooks 模块构建了“安全加固 + 事务性发件箱 + 指数退避调度器”企业级投递体系。

Webhooks 事件投递与重试全生命周期拓扑

200 OK 成功超时 / 5xx 故障超过 5 次重试

1. 业务集成事件 (如 order.paid)

2. WebhookEventRouter (匹配租户有效订阅)

3. 写入 WebhookDeliveryTask 队列 (状态: Pending)

4. IWebhookDeliveryService (HMAC-SHA256 签名 + SSRF 安全探测)

5. 发送 HTTP POST 至外部接收端

6. 标记为 Delivered 并记录耗时

7. 计算指数退避 (1m, 5m, 15m, 1h, 6h) -> 进入重试

8. 转入 Dead Letter Queue (死信队列 + 告警)


第一步:HMAC-SHA256 安全签名算法实现

框架在请求头中生成标准时间戳签名,接收方通过相同算法验签:

WebhookSigner.cs: HMAC-SHA256 签名引擎
using System.Security.Cryptography;
using System.Text;
public static class WebhookSigner
{
// 计算标准 HMAC-SHA256 签名:v1={HMAC(secret, timestamp + "." + payload)}
public static string ComputeSignature(string payload, string secret, long timestamp)
{
// 1. 构造待签名规范载荷
var signaturePayload = $"{timestamp}.{payload}";
var keyBytes = Encoding.UTF8.GetBytes(secret);
var payloadBytes = Encoding.UTF8.GetBytes(signaturePayload);
// 2. 纯内存计算哈希
using var hmac = new HMACSHA256(keyBytes);
var hashBytes = hmac.ComputeHash(payloadBytes);
// 3. 输出十六进制签名串
return $"v1={Convert.ToHexString(hashBytes).ToLowerInvariant()}";
}
}

第二步:防 SSRF 外部地址安全探测

在发起 HTTP 请求前,必须通过 IWebhookAddressValidator 解析真实 IP,严格禁止访问私有内网段:

WebhookAddressValidator.cs: SSRF 防御拦截器
using System.Net;
public sealed class WebhookAddressValidator : IWebhookAddressValidator
{
public async Task<bool> IsUrlSafeAsync(Uri targetUrl, CancellationToken ct)
{
// 1. 严禁非 HTTPS 协议(生产环境强制 TLS)
if (targetUrl.Scheme != Uri.UriSchemeHttps) return false;
// 2. 解析目标域名物理 IP
var hostAddresses = await Dns.GetHostAddressesAsync(targetUrl.Host, ct);
foreach (var ip in hostAddresses)
{
// 3. 拦截 Loopback (127.0.0.1) 与私有 RFC 1918 网段 (10.0.0.0/8, 192.168.0.0/16)
if (IPAddress.IsLoopback(ip) || ip.ToString().StartsWith("192.168.") || ip.ToString().StartsWith("10."))
{
return false; // 触发 SSRF 拦截
}
}
return true;
}
}

总结

Webhooks 模块为开放生态保驾护航:

  • 密态签名:HMAC-SHA256 + 时间戳杜绝重放攻击;
  • 智能退避:指数退避重试(1m $ ightarrow$ 5m $ ightarrow$ 15m $ ightarrow$ 1h)平滑应对三方网络抖动;
  • 零 SSRF 隐患:物理 IP 防护盾杜绝内网资产刺探。

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%