Sendgrid webhook 验证总是失败

问题描述 投票:0回答:2

我无法在我的应用程序中使用 Sendgrid 公钥验证。我已经配置了所有先决条件。 (添加了 API 密钥,启用了签名的 webhook 等)

这是我测试 webhook 的方法。

  1. 我在 Sendgrid 中注册一个 webhook.site url 作为 webhook
  2. 我从 Sendgrid 调用 webhook,这样我就可以调用 webbook.site
  3. 我将收到的请求作为 Curl 导出到 webhook.site。
  4. 导入Postman
  5. 在 Postman 中,我将 URL 更改为来自在我的本地主机中运行的后端服务的 URL,并调用来自 Postman 的调用。

这是我验证签名的代码。这是 Sendgrid 提供的内容的精确副本here.

public boolean VerifySignature(ECPublicKey publicKey, byte[] payload, String signature, String timestamp)
        throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException {

    // prepend the payload with the timestamp
    final ByteArrayOutputStream payloadWithTimestamp = new ByteArrayOutputStream();
    payloadWithTimestamp.write(timestamp.getBytes());
    payloadWithTimestamp.write(payload);

    // create the signature object
    final Signature signatureObject = Signature.getInstance("SHA256withECDSA", "BC");
    signatureObject.initVerify(publicKey);
    signatureObject.update(payloadWithTimestamp.toByteArray());

    // decode the signature
    final byte[] signatureInBytes = Base64.getDecoder().decode(signature);

    // verify the signature
    return signatureObject.verify(signatureInBytes);
}

现在,当从下面的控制器方法调用时,此方法始终返回 false。

    @PostMapping("/sendgrid-callback")
public boolean acceptSendgridCallback(
        @RequestBody String rawData,
        @RequestHeader("X-Twilio-Email-Event-Webhook-Timestamp") String timestamp,
        @RequestHeader("X-Twilio-Email-Event-Webhook-Signature") String signature
) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException, SignatureException, IOException, InvalidKeyException {

    System.out.println("Req body = \n" + rawData);

    ECPublicKey ecdsaKey = eventWebhook.ConvertPublicKeyToECDSA
            ("public key taken from sendgrid");

    boolean b = eventWebhook.VerifySignature(ecdsaKey, rawData, signature, timestamp);
    return b;
}

老实说,我找不到原因。

有人可以帮忙吗。

twilio webhooks sendgrid ecdsa sendgrid-api-v3
2个回答
1
投票

如果您使用单元测试或您自己的http请求进行测试,则需要在请求正文中添加

\r\n
才能通过验证。如果您使用实际的 sendgrid webhook 请求进行测试,则无需添加它。


0
投票

sendgrid 有一个用于 Java 的辅助工具。

https://github.com/sendgrid/sendgrid-java/blob/main/src/main/java/com/sendgrid/helpers/eventwebhook/EventWebhook.java

我稍微修改了一下

public class SendgridUtils {

    // Assuming publicKeyStr is the base64-encoded public key


    public static java.security.interfaces.ECPublicKey ConvertPublicKeyToECDSA(String publicKey)
            throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
        byte[] publicKeyInBytes = Base64.getDecoder().decode(publicKey);
        Security.addProvider(new BouncyCastleProvider());
        KeyFactory factory = KeyFactory.getInstance("ECDSA", "BC");
        return (ECPublicKey) factory.generatePublic(new X509EncodedKeySpec(publicKeyInBytes));
    }


    /**
     * Verify signed event webhook requests.
     *
     * @param publicKey: elliptic curve public key
     * @param payload:   event payload string in the request body
     * @param signature: value obtained from the
     *                   'X-Twilio-Email-Event-Webhook-Signature' header
     * @param timestamp: value obtained from the
     *                   'X-Twilio-Email-Event-Webhook-Timestamp' header
     * @return true or false if signature is valid
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws InvalidKeyException
     * @throws SignatureException
     * @throws IOException
     */
    public static boolean VerifySignature(ECPublicKey publicKey, String payload, String signature, String timestamp)
            throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException {
        return VerifySignature(publicKey, payload.getBytes(), signature, timestamp);
    }

    /**
     * Verify signed event webhook requests.
     *
     * @param publicKey: elliptic curve public key
     * @param payload:   event payload bytes in the request body
     * @param signature: value obtained from the
     *                   'X-Twilio-Email-Event-Webhook-Signature' header
     * @param timestamp: value obtained from the
     *                   'X-Twilio-Email-Event-Webhook-Timestamp' header
     * @return true or false if signature is valid
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws InvalidKeyException
     * @throws SignatureException
     * @throws IOException
     */
    public static boolean VerifySignature(ECPublicKey publicKey, byte[] payload, String signature, String timestamp)
            throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, SignatureException, IOException, IOException {

        // prepend the payload with the timestamp
        final ByteArrayOutputStream payloadWithTimestamp = new ByteArrayOutputStream();
        payloadWithTimestamp.write(timestamp.getBytes());
        payloadWithTimestamp.write(payload);

        // create the signature object
        final Signature signatureObject = Signature.getInstance("SHA256withECDSA", "BC");
        signatureObject.initVerify(publicKey);
        signatureObject.update(payloadWithTimestamp.toByteArray());

        // decode the signature
        final byte[] signatureInBytes = Base64.getDecoder().decode(signature);

        // verify the signature
        return signatureObject.verify(signatureInBytes);
    }

}

publicKey 你可以从 https://app.sendgrid.com/settings/mail_settings > Signed Event Webhook Requests 在验证密钥

© www.soinside.com 2019 - 2024. All rights reserved.