如何确保Stripe webhooks的安全性?

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

我将创建 Stripe Web 挂钩,并想知道如何确保安全性,以便只有 Stripe 可以访问我的 URL?

我正在使用 Laravel 和 Stripe 库。

php stripe-payments webhooks
4个回答
16
投票

文档中所述:

如果考虑安全性,或者如果需要确认 Stripe 发送了 Webhook,则您应该仅使用 Webhook 中发送的 ID,并直接从 Stripe API 请求其余详细信息。我们还建议您通过记录收到的事件来防范重放攻击,并且不要两次处理事件。

换句话说,没有办法确认请求来自哪里。因此,不要信任其任何数据,除了任何给定项目的 id。然后,您自己联系 Stripe API,请求具有给定 ID 的项目。这样您就知道从哪里获取数据,并且 Webhook 调用本质上只是成为一个通知,让您知道应该使用 API 进行签入。


5
投票

实际上,您可以将对 Webhook 的访问限制为仅 Stripe IP。这就是为什么 Stripe 更新了 webhooks ip 列表。

https://stripe.com/docs/ips

我刚刚为一个使用 Laravel 和 Stripe 的项目做了这件事。你可以这样做:

//Only accept connections from stripe ips.


    //Save stripe info for 24 hours for performance.
    $stripe_webhooks_ips = Cache::remember('stripe_webhooks_ips', 1440, function()
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_URL, 'https://stripe.com/files/ips/ips_webhooks.json');
        $result = curl_exec($ch);
        curl_close($ch);

        $json_result = json_decode($result,true);

        return $json_result['WEBHOOKS'];
    });



    if(in_array($_SERVER['REMOTE_ADDR'],$stripe_webhooks_ips)) {
        //Your Code Here.
    }

关于remote_addr变量的安全性: 信任 $_SERVER['REMOTE_ADDR'] 安全吗?

如果您使用代理或 Cloudfare 等 CDN 服务,请记住采取额外措施来获取源 IP。


2
投票

Stripe 对其发送给您的事件进行签名,因此您可以验证签名以检查 Stripe 是否是发送者。

Stripe 库将为您处理此问题,包括防止重放攻击。请参阅 https://stripe.com/docs/webhooks/signatures 上的文档。有一个 PHP 示例。

幂等性是一个单独的问题。您可能会多次收到事件,这是您需要处理的问题(通过跟踪事件 ID)。此页面提到了这一点:https://stripe.com/docs/webhooks/best-practices


0
投票

之前已经提到过,但我使用 stipe 提供给您的 webhook 密钥来检查请求的签名。以下示例来自Appwrite的函数模板。您可以在 GitHub 上查看验证函数的源代码。

validateWebhook(context, req) {
    try {
      const event = this.client.webhooks.constructEvent(
        req.bodyRaw,
        req.headers['stripe-signature'],
        process.env.STRIPE_WEBHOOK_SECRET
      );
      return /** @type {import("stripe").Stripe.DiscriminatedEvent} */ (event);
    } catch (err) {
      context.error(err);
      return null;
    }
  }
 const event = stripe.validateWebhook(context, req);
if (!event) {
  return res.json({ success: false }, 401);
}
© www.soinside.com 2019 - 2024. All rights reserved.