我是Play Framework的初学者(在这种情况下是2.5和Scala) - 我正在尝试通过为Facebook Messenger建立一个机器人来学习。但是我一直试图验证消息的签名。
我已经关注了Facebook文档并创建了一个webhook。它使用getRawMessages
处理POST请求(请参阅下面的代码)。然后,它尝试使用verifyPayload
函数验证请求是否由Facebook签名。但是我似乎无法得到计算的和实际的哈希匹配。
我从这个问题中起了带头作用:How to verify Instagram real-time API x-hub-signature in Java?这似乎正在做我想要的,但对于Instagram等效。但我似乎仍然无法做到正确。
val secret = "<facebooks secret token>"
def getRawMessages = Action (parse.raw) {
request =>
val xHubSignatureOption = request.headers.get("X-Hub-Signature")
try {
for {
signature <- xHubSignatureOption
rawBodyAsBytes <- request.body.asBytes()
} yield {
val rawBody = rawBodyAsBytes.toArray[Byte]
val incomingHash = signature.split("=").last
val verified = verifyPayload(rawBody, secret, incomingHash)
Logger.info(s"Was verified? $verified")
}
Ok("Test")
}
catch {
case _ => Ok("Test")
}
}
val HMAC_SHA1_ALGORITHM = "HmacSHA1"
def verifyPayload(payloadBytes: Array[Byte], secret: String, expected: String): Boolean = {
val secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_SHA1_ALGORITHM)
val mac = Mac.getInstance(HMAC_SHA1_ALGORITHM)
mac.init(secretKeySpec)
val result = mac.doFinal(payloadBytes)
val computedHash = Hex.encodeHex(result).mkString
Logger.info(s"Computed hash: $computedHash")
computedHash == expected
}
Facebook webhook docs州:
HTTP请求将包含一个包含的X-Hub-Signature标头 请求有效负载的SHA1签名,使用app secret作为 key,以sha1 =为前缀。您的回调端点可以验证这一点 用于验证有效载荷的完整性和来源的签名
请注意,计算是在转义的unicode上进行的 有效负载的版本,小写十六进制数字。如果你只是 根据解码的字节计算,你将得到一个不同的结果 签名。例如,字符串äöå应该转义为 \ u00e4 \ u00f6 \ u00e5。
我猜我错过的是将有效负载正确转义为unicode,但我似乎无法找到办法。在引用的问题中的答案似乎也只是获取字节数组而不用它做任何事情(jsonRawBytes = jsonRaw.asBytes();
)。
非常感谢任何有关如何进行的帮助。