我将创建 Stripe Web 挂钩,并想知道如何确保安全性,以便只有 Stripe 可以访问我的 URL?
我正在使用 Laravel 和 Stripe 库。
如文档中所述:
如果考虑安全性,或者如果需要确认 Stripe 发送了 Webhook,则您应该仅使用 Webhook 中发送的 ID,并直接从 Stripe API 请求其余详细信息。我们还建议您通过记录收到的事件来防范重放攻击,并且不要两次处理事件。
换句话说,没有办法确认请求来自哪里。因此,不要信任其任何数据,除了任何给定项目的 id。然后,您自己联系 Stripe API,请求具有给定 ID 的项目。这样您就知道从哪里获取数据,并且 Webhook 调用本质上只是成为一个通知,让您知道应该使用 API 进行签入。
实际上,您可以将对 Webhook 的访问限制为仅 Stripe IP。这就是为什么 Stripe 更新了 webhooks ip 列表。
我刚刚为一个使用 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。
Stripe 对其发送给您的事件进行签名,因此您可以验证签名以检查 Stripe 是否是发送者。
Stripe 库将为您处理此问题,包括防止重放攻击。请参阅 https://stripe.com/docs/webhooks/signatures 上的文档。有一个 PHP 示例。
幂等性是一个单独的问题。您可能会多次收到事件,这是您需要处理的问题(通过跟踪事件 ID)。此页面提到了这一点:https://stripe.com/docs/webhooks/best-practices。
之前已经提到过,但我使用 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);
}