检查网络钩子签名

概述 #

验证 Wooshpay 发送到 webhook 端点的事件。

Wooshpay 签名头 #

The Wooshpay-Signature 每个签名事件中的标头都包含一个时间戳和签名。

时间戳前缀为 t=,每个签名的前缀是 v1.

例如

Wooshpay-Signature:t=1492774577,v1=6fdfb9c357542b8ee07277f5fca2c6f728bae2dce9be2f91412f4de922c1bae4

Webhook 密钥 #

Wooshpay 会生成一个唯一的 秘钥 为每个网络钩子 whsec_

在验证签名之前,您需要从 webhook.secret 在 webhook 对象中。

webhook-secret-key

验证签名 #

通过比较 标题中的签名预期签名您可以验证即使是由 Wooshpay 发送的,而不是由第三方发送的。

要逐步验证签名,您可以按照以下指南进行操作:

步骤 1:从文件头提取时间戳和签名 #

使用 , 字符作为分隔符,得到一个元素列表。然后使用 = 字符作为分隔符,以获得前缀和值对。

前缀的值 t 对应于时间戳,而 v1 与签名相对应。您可以舍弃所有其他元素。

例如

t=1687845304,v1=6fdfb9c357542b8ee07277f5fca2c6f728bae2dce9be2f91412f4de922c1bae4

步骤 2:准备 签名支付负载 字符串 #

The 签名支付负载 字符串是通过连接创建的:

  • 时间戳(字符串)
  • 角色 .
  • 实际的 JSON 有效负载(请求正文)

例如

1687845304+.+JSON 有效负载

1687845304.{
  "id":"evt_1NNUrjL6kclEVx6Mb1x5dKJ3",
  "对象":"事件"、
  "api_version":"2022-11-15"2022-11-15",
  "创建":1687845303,
  "数据":{
    "对象":{
      "id":"prod_O9oUVgsSaordCT"、
      "对象":"产品"、
      "active": true、
      "livemode": true、
      "名称":"test"、
      "类型":"服务"、
  "livemode": true、
  "pending_webhooks":1,
  "type":"product.created
}

步骤 3:确定预期签名 #

使用 SHA256 哈希函数计算 HMAC。

  • 使用端点的网络钩子秘密作为 密钥您可以从以下网站获取 webhook.secret 在网络钩子对象中
  • 使用 签名支付负载 字符串作为 信息 这是您在第 2 步中已经准备好的。

通过 密钥 + 信息,就可以计算出一个 HMAC 字符串,即 预期签名

例如

 public static void main(String[] args) {
        String webhookSecret = "whsec_261V2mfsXt1BsOjJbHaQOxnTzhWZKrUE";
        String timestamp = "1687845304";
        String requestBody = "{\"id\":\"evt_1NNUrjL6kclEVx6Mb1x5dKJ3\",\"object\":\"event\",\"api_version\":\"2022-11-15\",\"created\":1687845303,\"data\":{\"object\":{\"id\":\"prod_O9oUVgsSaordCT\",\"object\":\"product\",\"active\":true,\"livemode\":true,\"name\":\"test\",\"type\":\"service\",\"livemode\":true,\"pending_webhooks\":1,\"type\":\"product.created\"}";
        String signedPayload = timestamp+". "+requestBody;
        String signature = hmacSha256(webhookSecret,signedPayload);
        String WooshpaySignature = "t="+timestamp+",v1="+signature;
    }

    /**
     * HMAC-SHA256
     */
    public static String hmacSha256(String secret, String message) {
        字符串 res;
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKey secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            mac.init(secretKey);
            byte[] hash = mac.doFinal(message.getBytes());
            res = Hex.encodeHexString(hash);
        } catch (Exception e) {
            return null;
        }
        return res;
    }

步骤 4:比较签名 #

比较 标题中的签名预期签名.

对于相等匹配,计算 当前时间戳收到的时间戳然后再决定差异是否在您的承受范围之内。

为了防止定时攻击,可以使用恒定时间字符串比较法,将预期签名与收到的每个签名进行比较。

What are your feelings
Updated on 8月 5, 2023