如何用Node.js正确验证Shopware 6应用的确认请求
问题
我正在开发Shopware 6应用,参考官方应用基础指南搭建,但采用Node.js/Express而非PHP开发。参照官方AppBundle中的RequestVerifier实现了签名验证模块,但POST确认请求的签名始终验证失败。
我的验证模块代码如下:
import { Request } from 'express'; const crypto = require('crypto'); const SHOPWARE_APP_SIGNATURE_HEADER = 'shopware-app-signature'; const SHOPWARE_SHOP_SIGNATURE_HEADER = 'shopware-shop-signature'; function authenticateRegistrationRequest(req: Request, appSecret: string): void { const signature = getSignatureFromHeader(req, SHOPWARE_APP_SIGNATURE_HEADER); verifySignature(appSecret, buildValidationQuery(req), signature); } function getSignatureFromHeader(req: Request, headerName: string): string { const signatureHeader = req.get(headerName); if (!signatureHeader) { throw new Error('Signature is not present in request'); } return signatureHeader; } function buildValidationQuery(req: Request): string { const queries = req.query; return `shop-id=${queries['shop-id']}&shop-url=${queries['shop-url']}×tamp=${queries.timestamp}`; } function verifySignature(secret: string, message: string, signature: string): void { const hmac = crypto.createHmac('sha256', secret).update(message).digest('hex'); if (hmac !== signature) { throw new Error('Signature could not be verified'); } } function authenticatePostRequest(req: Request, shop: Shop): void { const signature = getSignatureFromHeader(req, SHOPWARE_SHOP_SIGNATURE_HEADER); // TODO: Verify Request body contents correctly verifySignature(shop.getShopSecret(), JSON.stringify(req.body), signature); } module.exports = { authenticateRegistrationRequest, authenticatePostRequest };
其中authenticateRegistrationRequest能正常通过签名验证,但authenticatePostRequest始终失败。我原本认为JSON.stringify(req.body)和PHP中的$request->getBody()->getContents()等价,但实际验证不匹配。
验证时传入的参数详情:
shop.getShopSecret():76d73cb7094d91a2a8ccb7eba5f30b649339879cJSON.stringify(req.body):{"apiKey":"SWIAAGRXVXZVVTDHRWHYEWDRQG","secretKey":"dUpNY3ZjbzNKUFJIVE40allqcnl4bHFQV0lyVjhBRWJvNzJhZ2o","timestamp":"1669233633","shopUrl":"http://localhost:8888","shopId":"HBUXtMoPbXmKzkNq"}signature:0597c71bda40fa25d0f4edff3c54eedbfb26bc95cef202c8f9f03bb7c5fdc478
解决方案
问题根源在于Express的body parser配置。我使用express.json()解析请求体,它处理后的req.body再通过JSON.stringify()生成的字符串,与Shopware生成签名时使用的原始请求体在斜杠转义规则上不一致。
修改authenticatePostRequest中的验证代码,手动对正斜杠进行转义即可解决:
verifySignature(shop.getShopSecret(), JSON.stringify(req.body).replace(/\//g, '\\/'), signature);
我的body parser配置如下:
import express from 'express'; const app = express(); app.use(express.json());
内容的提问来源于stack exchange,提问作者lucamario
相关产品推荐
相关产品推荐

