【发布时间】:2016-05-19 19:56:06
【问题描述】:
我是 Play 框架(在本例中为 2.5 和 Scala)的初学者 - 我正在尝试通过为 Facebook Messenger 构建机器人来学习。但是,我在尝试验证消息的签名时遇到了困难。
我遵循 Facebook 文档并创建了一个 webhook。它使用getRawMessages 处理 POST 请求(参见下面的代码)。然后尝试验证请求是否由 Facebook 使用 verifyPayload 函数签名。但是我似乎无法让计算的哈希值和实际的哈希值匹配。
我已经率先查看了这个问题: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 签名,使用应用程序密钥作为 键,并以 sha1= 为前缀。您的回调端点可以验证这一点 签名以验证有效载荷的完整性和来源
请注意,计算是根据转义的 unicode 进行的 有效载荷的版本,带有小写十六进制数字。如果你只是 根据解码的字节计算,你最终会得到一个不同的 签名。例如,字符串 äöå 应转义为 \u00e4\u00f6\u00e5.
我猜我缺少的是让有效负载正确转义为 unicode,但我似乎无法找到一种方法来做到这一点。并且引用问题中的答案似乎也只是获取字节数组而无需对其进行任何操作(jsonRawBytes = jsonRaw.asBytes();)。
任何有关如何进行的帮助将不胜感激。
【问题讨论】:
标签: facebook scala playframework facebook-webhooks