2016-11-18 6 views
2

説明が少し長いので、私にご負担ください。FacebookメッセンジャーAPI不完全な内容のリクエスト本体

バックエンドで私のsails.js/node.jsサーバとMongoDBデータベースを使用するFacebookメッセンジャーボットを構築しています。

私の帆アプリでは、ユーザーからテキストを受け取った後に実行される操作を処理するコントローラのメソッドにポリシーを適用しました。このポリシーでは、ドキュメント(https://developers.facebook.com/docs/messenger-platform/webhook-reference - "セキュリティ"セクション)に従い、要求ヘッダーに含まれるx-hub-signatureと要求ペイロード(body)のsha1ダイジェストを比較しています。

これで、ボットにメッセージを送信しているときはいつでも、リクエストの署名と私が計算した署名が違っていて、それ以上進まないというポリシーがあります。私はダイジェストを計算する際に使用すべきアプリの秘密を二重にチェックし、正しいと思われる。私が見つけたもう1つの違いは、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"}}]}]} 

答えて

4

@と%のような特定の文字が問題になっていたと思いますeir unicodeのエスケープシーケンスをドキュメントに指定されていて、元の文字列化されたJSONで置き換えられます。私はそれらを変換し、新しい文字列のhmac署名を計算し、それが一致しました。

また、なぜそれが働いていたのか、それが特定のケースではなかった理由は、文字列化されているその文字列に特殊文字が存在するためだと思います。 @または%の文字がない場合は問題なく動作します。

これは私はそれを解決する方法である - calculatedSignature、ペイロード= JSON.stringify(req.body)、 if内部VaRのHMACと、

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!'); 
    } 
関連する問題