我创建了一个汇总多个Shopify商店的订单处理的信息中心。它是一个私人应用程序,因此我将每个Shopify商店的API凭据和webhook秘密保存在我的数据库中。我用一个存储为环境变量的密钥加密了所有这些敏感的东西。对于任何给定的事件,我将所有Shopify商店指向相同的回调URL。因此,对于每个URL,我必须针对存储在数据库中的所有可能的webhook秘密来验证请求主体。我有两个问题:
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;
});
}

答案 0 :(得分:0)
通常,您应该真正存储在数据库中的唯一内容是应用程序的商店访问令牌以及商店登录的任何其他验证数据。每次使用您的应用程序共享密钥和webhook即将发送给您的数据向您的应用发送请求时,Webhook签名和生成方式都不同。
使用您的应用程序共享密钥验证Webhooks,并将邮件请求数据验证到标头中发送的HMAC签名: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')
通常没有必要将这些信息存储在数据库中,只是计算它并使用中间件即时验证它。我希望这会有所帮助。