解释有点长,所以请忍受我。
我正在构建一个Facebook Messenger机器人,该机器人在后端使用我的sails.js / node.js服务器和一个MongoDB数据库。
在我的sails应用程序中,我已将策略应用于控制器的方法,该方法处理从用户处接收到文本后要执行的操作。在此政策中,我将遵循文档(https://developers.facebook.com/docs/messenger-platform/webhook-reference- “安全性”部分),并将x-hub-signature
请求标头中的内容与的sha1摘要进行比较请求有效负载(正文)。
因此,现在无论何时我向机器人发送一条消息,它都在策略中说,请求中的签名和我计算出的签名是不同的,因此不再进一步。我仔细检查了应在计算摘要时使用的应用程序密码,这似乎是正确的。我发现的另一个区别是,Facebook请求还在其标头中发送了一个“ content-length”字段,该字段与他们在同一请求中发送的正文的字符长度不同。这就是我认为使用不同签名的原因,但是我无法解决它,而无法找到问题的根源。
还要注意的另一件事是,引发此不匹配错误的同一代码在某些时间(实际上,在大多数时间)可以完美运行。
那么有人可以帮我吗?我将永远感激不尽:)
这是政策中的代码
var crypto = require('crypto');
if(req.headers['x-hub-signature']){
//console.log('req headers -----', JSON.stringify(req.headers));
//console.log('req body -----', JSON.stringify(req.body));
var hmac, calculatedSignature, payload = req.body;
hmac = crypto.createHmac('sha1', app_secret);
hmac.update(JSON.stringify(payload));
calculatedSignature = 'sha1='+hmac.digest('hex');
//console.log("signature calculatedSignature",calculatedSignature);
if(calculatedSignature === req.headers['x-hub-signature']){
return next();
}else{
res.forbidden('You shall not pass!');
}
}
这是一个示例请求标头-
{"host":"e93d4245id.ngrok.io","accept":"*/*","accept-encoding":"deflate, gzip","content-type":"application/json","x-hub-signature":"sha1=d0cd8177add9b1ff367d411942603b0d08183964","content-length":"274","x-forwarded-proto":"https","x-forwarded-for":"127.0.0.1"}
这是来自同一请求的主体-
{"object":"page","entry":[{"id":"1778585282425767","time":1479476014038,"messaging":[{"sender":{"id":"userId"},"recipient":{"id":"recipientId"},"timestamp":1479468097895,"message":{"mid":"mid.1479468097895:efdc7d2c68","seq":2355,"text":"Hahahaha"}}]}]}
我认为问题在于需要将某些特定字符(例如@和%)转换为文档中指定的Unicode转义序列,并替换为原始的字符串化JSON。我对它们进行了转换,然后计算了新字符串的hmac签名,并对其进行了匹配。
我还认为它起作用的原因以及在某些情况下它不起作用的原因是我认为是因为要字符串化的字符串中存在特殊字符。如果它没有字符@或%,那么它可以正常工作。
这就是我解决的方式-在if
var hmac,calculatedSignature,payload = JSON.stringify(req.body);中;
var resStr = payload.replace(/\@|\%/g,function(a, i){
hex = payload.charCodeAt(i).toString(16);
var s = "\\u" + ("000"+hex).slice(-4);
return s;
});
hmac = crypto.createHmac('sha1', app_secret);
hmac.update(resStr);
calculatedSignature = 'sha1='+hmac.digest('hex');
if(calculatedSignature === req.headers['x-hub-signature']){
return next();
}else{
res.forbidden('You shall not pass!');
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句