我创建了一个仪表板,用于聚合多个 Shopify 商店的订单处理。这是一个私有(private)应用程序,因此我将每个 Shopify 商店的 API 凭据和 Webhook key 保存在我的数据库中。我已经使用存储为环境变量的 key 对所有这些敏感内容进行了加密。对于任何给定事件,我将所有 Shopify 商店定向到相同的回调 URL。因此,对于每个 url,我必须根据存储在数据库中的所有可能的 Webhook secret 来验证请求正文。我有两个问题:
- 这是保护商店 API 凭据和 Webhook secret 的可接受的方法吗?
- 如果我的 secret 存储在数据库中,如何同步验证请求正文?我的验证函数如下。
verify: (buffer, hmacHeader) => {
Brand.find().exec((err, brands) => {
if (!err && brands) {
const allWebhookSecrets = brands.map(brand => {
console.log(`encrypted webhook secret is: ${brand.shopify_webhook_secret_encrypted}`)
return encryption.decrypt(brand.shopify_webhook_secret_encrypted);
});
const webhookIsValid = allWebhookSecrets.some(secret => {
var hmac = crypto.createHmac('sha256', secret)
.update(buffer)
.digest('base64');
return hmac == hmacHeader;
});
console.log(`webhookIsValid: ${webhookIsValid}`);
return webhookIsValid;
}
return false;
});
}
最佳答案
通常,您真正应该在数据库中存储的唯一内容是应用程序的商店访问 token 以及商店登录的任何其他验证数据。每次使用应用程序共享 key 和 Webhook 将发送给您的数据将请求发送到您的应用程序时,Webhook 签名都会以不同的方式生成。
使用您的应用共享 key 和 header 中发送的 HMAC 签名的发布请求数据来验证 Webhook:X-Shopify-Hmac-SHA256
。
这是我的 webhook 验证中间件的简化 Nodejs 实现
function verify_webhook(postData, hmac) {
if (!hmac || !postData || typeof postData !== 'object') {
return false;
}
const calculatedSignature = crypto.createHmac('sha256', process.env.SHOPIFY_SHARED_SECRET)
.update(postData)
.digest('hex');
return calculatedSignature === hmac;
}
其中 postData 和 hmac 是 JSON.stringify(req.body)
和 req.get('X-Shopify-Hmac-SHA256')
通常没有必要将此信息存储在数据库中并仅使用中间件即时计算和验证它。我希望这会有所帮助。
关于javascript - 使用许多可能的 secret 验证 Shopify webhook,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45292263/