【问题标题】:Why Stripe's webhooks do not need verify signature?为什么 Stripe 的 webhook 不需要验证签名?
【发布时间】:2016-08-29 15:34:58
【问题描述】:

doc (https://stripe.com/docs/webhooks) 和 SDK(stripe-php) 都没有使用任何签名方法。所以我怀疑,如果有人假冒官方 webhook 发件人怎么办?

在 SDK 中,只有成功获取事件 id 才会认为是一个好的 webhook,我认为这太冒险了,不是吗?

【问题讨论】:

  • stripe 好像听到了你的声音。

标签: php stripe-payments


【解决方案1】:

Stripe 确实为网络钩子提供了签名。看这里:https://stripe.com/docs/webhooks#signatures

你也可以看看这篇文章:https://www.truespotmedia.com/testing-webhooks-in-stripe-with-php/

下面是一些示例代码:

// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("your secret api key");

// You can find your endpoint's secret in your webhook settings
$endpoint_secret = "whsec_...";

$payload = @file_get_contents("php://input");
$sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"];
$event = null;

try {
  $event = \Stripe\Webhook::constructEvent(
    $payload, $sig_header, $endpoint_secret
  );
} catch(\UnexpectedValueException $e) {
  // Invalid payload
  http_response_code(400); // PHP 5.4 or greater
  exit();
} catch(\Stripe\Error\SignatureVerification $e) {
  // Invalid signature
  http_response_code(400); // PHP 5.4 or greater
  exit();
}

// Do something with $event

http_response_code(200); // PHP 5.4 or greater

【讨论】:

    【解决方案2】:

    有两种方法可以做到这一点。它们已经涵盖了,但我会将所有内容整合到一个答案中。

    选项 1

    检查事件是否有效(如果不是则抛出异常)。

    \Stripe\Event::retrieve($event_id)
    

    选项 2

    使用您仪表板中的whsec* 密钥对Stripe-Signature 标头进行HMAC。

    // Set your secret key: remember to change this to your live secret key in production
    // See your keys here: https://dashboard.stripe.com/account/apikeys
    \Stripe\Stripe::setApiKey("sk_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
    
    // You can find your endpoint's secret in your webhook settings
    $endpoint_secret = "whsec_...";
    
    $payload = @file_get_contents("php://input");
    $sig_header = $_SERVER["HTTP_STRIPE_SIGNATURE"];
    $event = null;
    
    try {
      $event = \Stripe\Webhook::constructEvent(
        $payload, $sig_header, $endpoint_secret
      );
    } catch(\UnexpectedValueException $e) {
      // Invalid payload
      http_response_code(400); // PHP 5.4 or greater
      exit();
    } catch(\Stripe\Error\SignatureVerification $e) {
      // Invalid signature
      http_response_code(400); // PHP 5.4 or greater
      exit();
    }
    
    // Do something with $event
    
    http_response_code(200); // PHP 5.4 or greater
    

    来自https://stripe.com/docs/webhooks/signatures的代码

    选项 1 更简单,需要对 API 进行额外调用,但选项 2 要求您在应用程序中存储额外的密钥并需要代码(我更喜欢选项 1)。我今天咨询了 Stripe 支持,他们确认它们在验证 API 调用的有效性方面都一样好,所以这是一个选择问题。

    【讨论】:

    • 选项 1 很棒,我没有在其他地方找到类似的解决方案
    【解决方案3】:

    您可以通过保存事件 id 然后从条带中检索事件以确保事件有效来解决此问题:

    \Stripe\Event::retrieve($event_id)
    

    【讨论】:

    • 是的,我知道。我在 SDK 中看到了代码,但我不明白为什么 stripe 认为成功检索 event_id 是合法的 webhook,为什么?如果有人伪造数据只是使用相同的可检索事件和相同的事件 ID 怎么办?
    • Phoenix,您正在直接从 Stripe 检索事件,因此为了实现这一点,伪造者必须拿出 Stripe 生成的相同事件 id 才能实现。
    • 你知道,这很糟糕。对于每个事件,我们都需要额外调用 stripe 的服务器。我想知道为什么他们没有像所有其他公司那样的签名机制。
    猜你喜欢
    • 2021-09-18
    • 1970-01-01
    • 2016-02-08
    • 2021-01-14
    • 2016-11-17
    • 2016-03-16
    • 2015-11-14
    • 2018-03-09
    • 2020-07-17
    相关资源
    最近更新 更多