Webhook 安全工具

Webhook Secret 生成器

生成用于签名校验的 Webhook Secret,适用于 GitHub、Stripe、Shopify 等集成。

生成密钥

安全、随机、本地生成。

安全

输出格式:自定义字符集

配置
32 字符
864128

Webhook 签名检查清单

时间戳校验

拒绝 5 分钟前的请求,降低重放攻击风险。

常量时间比较

比较签名时使用 timingSafeEqual 或 compare_digest。

双密钥轮换

保留两把密钥以便平滑轮换,不丢 Webhook。

资源入口

什么是 Webhook Secret?

Webhook Secret 是共享密钥,用于对 Webhook 载荷进行签名并验证真实性。GitHub、Stripe、Shopify 等在发送 Webhook 时会携带 HMAC 签名,你可以用该密钥验证请求是否被篡改。

我们的生成器生成可用于生产环境的安全密钥。请勿在前端或公开仓库中泄露该密钥。

Webhook 签名验证流程

  1. 服务端生成签名: Webhook 提供方使用你的密钥对 payload 生成 HMAC 签名。
  2. 签名随请求发送: 签名通过请求头携带(如 X-Hub-Signature、X-Stripe-Signature)。
  3. 你的服务接收请求: 接收 payload 与签名头。
  4. 本地计算签名: 使用本地密钥重新计算 HMAC 签名。
  5. 比较签名: 一致则为可信 Webhook。

各平台 Webhook 签名方式

GitHub Webhooks

使用 X-Hub-Signature-256,HMAC-SHA256。

Header 格式:sha256=<signature>

Stripe Webhooks

Stripe-Signature 头,包含时间戳与版本。

HMAC-SHA256,含重放保护

Shopify Webhooks

使用 X-Shopify-Hmac-SHA256,Base64 编码签名。

Base64 编码的 HMAC-SHA256

通用 Webhooks

多数平台使用 HMAC-SHA256 并通过头部传递签名。

常见头:X-Signature、X-Webhook-Signature

Webhook 验证示例

以下示例演示如何验证 Webhook 签名:

Node.js - 验证 GitHub Webhook

const crypto = require('crypto');

function verifyGitHubWebhook(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  const digest = 'sha256=' + hmac.update(payload).digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(digest)
  );
}

// Usage
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-hub-signature-256'];
  const payload = JSON.stringify(req.body);
  const secret = process.env.WEBHOOK_SECRET;
  
  if (verifyGitHubWebhook(payload, signature, secret)) {
    // Webhook is authentic
    res.status(200).send('OK');
  } else {
    res.status(401).send('Unauthorized');
  }
});

Python - 验证 Stripe Webhook

import stripe
import os

# Stripe provides a helper library
stripe.api_key = os.environ['STRIPE_API_KEY']
endpoint_secret = os.environ['WEBHOOK_SECRET']

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.data
    sig_header = request.headers.get('Stripe-Signature')
    
    try:
        event = stripe.Webhook.construct_event(
            payload, sig_header, endpoint_secret
        )
        # Webhook verified successfully
        return 'OK', 200
    except ValueError:
        return 'Invalid payload', 400
    except stripe.error.SignatureVerificationError:
        return 'Invalid signature', 401

Webhook Secret 最佳实践

  • 长度足够: 至少 32 字符(256 bit)以抵抗暴力破解。
  • 安全存储: 放在环境变量或密钥管理系统中,避免写入代码仓库。
  • 每次都校验: 处理 payload 前必须验证签名。
  • 常量时间比较: 比较签名时使用 timing-safe 比较函数。
  • 重放防护: 校验时间戳并拒绝过期请求。
  • 定期轮换: 按计划轮换密钥,泄露风险时立即替换。
  • 只用 HTTPS: Webhook 端点必须使用 HTTPS。
  • 记录失败: 记录验证失败以便审计与排查。

Webhook Secret 生成器常见问题

Webhook Secret 应该多长?

建议至少 32 字符(256 bit)。我们默认输出适合生产的长度。

可否多个服务共用一个 Secret?

不建议。不同服务应使用不同密钥,便于独立轮换与隔离风险。

Secret 泄露怎么办?

立即生成新密钥并更新服务端与平台配置,同时排查可疑请求。

每种事件要不同的 Secret 吗?

通常同一服务一个 Secret 即可。如果同服务有多个 Webhook 端点,建议每个端点用不同 Secret。

相关密钥生成器

隐私与安全

所有 Webhook Secret 均在浏览器本地生成,使用 Web Crypto API 的加密级随机数。不会上传或存储任何数据。