要与服务集成,我需要在Play 2.4(scala)服务器上实现REST端点。该服务向我发送了一份GET请求,该请求是用他们给我的密钥和秘密签署的。
我需要验证请求是否来自他们
我的方法是:
val accessTokenOpt: Option[String] = request.headers.get(Security.AUTH_HEADER)
(accessTokenOpt, Security.consumer) match {
case (Some(accessToken), Some(consumer)) => {
val calculator = new OAuthCalculator(consumer, RequestToken("", ""))
val expected = WS.url(s"http://${request.host}${request.uri}").sign(calculator)
(expected.headers.get(Security.AUTH_HEADER), accessToken) match {
case (Some(exp), Some(actual)) if exp == actual =>
//good
case (Some(exp), Some(actual)) =>
//mismatch
case (e, a) =>
//missing tokens. :(
}
}
case _ => //bad
}
问题是expected.headers.(Security.AUTH_HEADER)
返回None
我错过了代码中的小东西,还是我的整个方法都错了?
答案 0 :(得分:0)
我认为您的方法是正确的,并且从完全相同的参数计算的oauth签名将始终匹配。但是你必须考虑一些像nonce和timestamp这样的参数,为了做到这一点,我必须直接使用签名的Java类。
以下是我设法让它发挥作用的方式。请记住,在我的情况下,与我的REST端点联系的外部服务发送的Authorization标头包含用于计算oauth_signature值的所有信息,除了我拥有的oauth秘密。
private def getProtocolFromRequest[T](request: Request[T]): String = {
// To handle the case where a SSL offloading is involved
request.headers.get(HeaderNames.X_FORWARDED_PROTO) match {
case Some(forwardedProto: String) => forwardedProto
case _ => if(request.secure) "https" else "http"
}
}
def isOAuthSignatureValid[T](request: Request[T]): Boolean = {
request.headers.get(com.ning.http.client.oauth.OAuthSignatureCalculator.HEADER_AUTHORIZATION) match {
case Some(authorizationHeaders) =>
val AuthRegex = ".*oauth_nonce=\"([^\"]*)\".*oauth_signature=\"([^\"]*)\".*oauth_timestamp=\"([^\"]*)\".*".r
authorizationHeaders match {
case AuthRegex(nonce: String, providedSignature: String, timestamp: String) =>
val signatureCalculator = new OAuthSignatureCalculator(new com.ning.http.client.oauth.ConsumerKey(oauthKey, oauthSecret), new com.ning.http.client.oauth.RequestToken(null, ""))
val params = request.queryString.map(query => new Param(query._1, query._2.head)).toSeq
val protocol = getProtocolFromRequest(request)
val url = s"$protocol://${request.host}${request.path}"
val expectedSignature = signatureCalculator.calculateSignature(
request.method,
Uri.create(url),
timestamp.toInt,
nonce,
new util.ArrayList(),
scala.collection.JavaConversions.seqAsJavaList(params)
)
expectedSignature.equals(URLDecoder.decode(providedSignature, "UTF-8"))
case _ => false
}
case _ => false
}
}
对我有用的流程如下:
希望这可以帮助某人