WooCommerce的SHA256 webhook签名从不validation

我正在从woocommerce网站接收webshook到一个nodejs / express应用程序。 我试图validationwebhook的签名来certificate真实性,但是我计算的散列绝对不会与woocommerce在签名头中报告的签名相对应。

这是我用来validation真实性的代码:

function verifySignature(signature, payload, key){ var computedSignature = crypto.createHmac("sha256", key).update(payload).digest('base64'); debug('computed signature: %s', computedSignature); return computedSignature === signature; } 

这个函数被调用了以下参数:

 var signature = req.headers['x-wc-webhook-signature']; verifySignature(signature, JSON.stringify(req.body), config.wooCommence.accounts.api[config.env].webhookSecret) 

webhook的签名报头将签名报告为BewIV/zZMbmuJkHaUwaQxjX8yR6jRktPZQN9j2+67Oo= 。 但是,上述操作的结果是S34YqftH1R8F4uH4Ya2BSM1rn0H9NiqEA2Nr7W1CWZs=

我已经手动configuration了webhook上的秘密,正如你在上面的代码中看到的,这个秘密在快速应用程序中也是硬编码的。 所以要么是我错误的有效载荷来计算签名,要么是有其他的东西让我无法validation这些签名。

将不胜感激任何指针来帮助我解决这个问题。

老问题,但也许这有助于一些可怜的灵魂在那里。 签名需要检查身体,而不是它包含的JSON。 即身体的原始字节。

伪:

  byte[] body = request.Body; string signature = request.Header["X-WC-Webhook-Signature"]; byte[] secretUtf8 = GetUtf8Bytes("yoursecrethere"); byte[] hash = HMAC_SHA256.ComputeHash(body, secretUtf8); string hashBase64 = ToBase64String(hash); bool isValid = hashBase64 == signature; 

对于使用节点的人来说,这应该是个诀窍。

 var processWebHookSignature = function (secret, body, signature) { signatureComputed = crypto.createHmac('SHA256', secret).update( new Buffer(JSON.stringify(body), 'utf8')).digest('base64'); return ( signatureComputed === signature ) ? true : false; } 

我偶然发现了一个解决scheme,有一个Asp.NET应用程序检查Woocommerce Web钩子的签名。 我的答案是基于Johannes提供的伪代码,它工作得很好。 我实现了一个自定义控制器属性来拦截请求,并在签名达到API控制器方法之前检查签名:

 public class HmacSignatureFilter : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var requestContent = actionContext.Request.Content; var jsonContent = requestContent.ReadAsStringAsync().Result; var byteContent = requestContent.ReadAsByteArrayAsync().Result; //if the request contains this, it's the verification request from Woocommerce //when the webhook is created so let it pass through so it can be verified if (!jsonContent.Contains("webhook_id")) { var requestSignature = actionContext.Request.Headers; var bodyHash = HashHMAC("test", byteContent); //this is the shared key between Woo and custom API. should be from config or database table. var signature = actionContext.Request.Headers.GetValues("x-wc-webhook-signature"); if (bodyHash != signature.FirstOrDefault()) { throw new HttpResponseException(HttpStatusCode.Forbidden); } } base.OnActionExecuting(actionContext); } private static string HashHMAC(string key, byte[] message) { var keyBytes = Encoding.UTF8.GetBytes(key); var hash = new HMACSHA256(keyBytes); var computedHash = hash.ComputeHash(message); return Convert.ToBase64String(computedHash); } } 

然后在你的Api控制器中使用filter:

 [RoutePrefix("api/woo")] public class WooController : ApiController { public SomeService _service; public WooController() { this._service = new SomeService(); } // POST api/values [Route("orderCreated")] [HttpPost] [HmacSignatureFilter] public string Post() { var requestContent = Request.Content; var jsonContent = requestContent.ReadAsStringAsync().Result; //this is the test request from Woocommerce. Don't do anything but //respond so it can verify the endpoint if (jsonContent.Contains("webhook_id")) { return "Webhook Test Success"; } var wooOrder = JsonConvert.DeserializeObject<WooOrderModel>(jsonContent); //call a service to use the order data provided by WooCommerce _service.AddOrder(wooOrder); return "Success"; } } 

注意:哈希代码是从这个SOpost引用的 。

哈希必须在“原始的身体”上计算。 当在“快速申请”中使用并使用JSON bodyParser中间件“原始主体”时,请参阅如何在bodyparser之前访问请求的原始主体? 保持“原始的身体”。

例如:

 // 'misuse' verify option app.use(bodyParser.json({ verify: function(req,res,buf) { req.rawBody=buf; } })); var wcSignature = req.get('X-Wc-Webhook-Signature'); debug('wc signature: %s', wcSignature); var calculatedSignature = crypto.createHmac('SHA256', secret) .update(req.rawBody, 'utf8') .digest('base64'); debug('calculated signature: %s', calculatedSignature);