Facebook messenger API请求正文中的内容不完整

Sim*_*mer 2 javascript node.js messenger sails.js facebook-messenger

解释有点长,请耐心等待.

我正在构建一个Facebook messenger bot,它在后端和MongoDB数据库中使用我的sails.js/node.js服务器.

在我的sails应用程序中,我已经将策略应用于控制器的方法,该方法处理在从用户接收文本之后要执行的操作.在本政策中,我遵循文档(https://developers.facebook.com/docs/messenger-platform/webhook-reference - "安全性"部分)并将x-hub-signature请求标题中的内容与sha1摘要进行比较.请求有效载荷(正文).

因此,现在每当我向机器人发送消息时,它在策略中都表示请求中的签名和我计算的签名是不同的,因此不会更进一步.我仔细检查了应该在计算摘要时应该使用的app秘密,它似乎是正确的.我发现的另一个不同之处在于,Facebook请求还在其标题中发送"内容长度"字段,这与他们在同一请求中发送的正文的字符长度不同.这就是我认为不同签名的原因,但我无法解决它并找到问题的根源,为什么会发生这种情况.

另外需要注意的是,抛出此不匹配错误的相同代码在某些时间(实际上,大多数时间)运行完美.

有人可以帮帮我吗?我将永远感激:)

这是政策中的代码

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!');
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个示例请求标头 -

{"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"}
Run Code Online (Sandbox Code Playgroud)

而这是来自同一要求的身体 -

{"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"}}]}]}
Run Code Online (Sandbox Code Playgroud)

wad*_*ali 6

我认为问题是需要将某些特定字符(如@和%)转换为其文档中指定的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!');
    }
Run Code Online (Sandbox Code Playgroud)