§OAuth
OAuth 是一种简单的方式来发布和交互受保护的数据。它也是人们授予您访问权限的安全可靠方式。例如,它可以用于访问您用户在 Twitter 上的数据。
OAuth 有两个截然不同的版本:OAuth 1.0 和 OAuth 2.0。版本 2 足够简单,可以在没有库或帮助程序的情况下轻松实现,因此 Play 仅提供对 OAuth 1.0 的支持。
§用法
要使用 OAuth,首先将 ws
添加到您的 build.sbt
文件中
libraryDependencies ++= Seq(
ws
)
§所需信息
OAuth 要求您将应用程序注册到服务提供商。确保检查您提供的回调 URL,因为如果它们不匹配,服务提供商可能会拒绝您的调用。在本地工作时,您可以使用 /etc/hosts
在本地机器上伪造一个域名。
服务提供商将为您提供
- 应用程序 ID
- 密钥
- 请求令牌 URL
- 访问令牌 URL
- 授权 URL
§身份验证流程
大部分流程将由 Play 库完成。
- 从服务器获取请求令牌(在服务器到服务器的调用中)
- 将用户重定向到服务提供商,用户将在那里授权您的应用程序使用其数据
- 服务提供商将把用户重定向回来,并提供一个 /验证器/
- 使用该验证器,将 /请求令牌/ 交换为 /访问令牌/(服务器到服务器的调用)
现在,/访问令牌/ 可以传递给任何访问受保护数据的调用。
有关 OAuth 流程的更多详细信息,请访问 The OAuth Bible。
§示例
要在控制器中实现流程,请定义密钥和消费者密钥,并检索令牌和密钥
val KEY = ConsumerKey("xxxxx", "xxxxx")
val oauth = OAuth(
ServiceInfo(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize",
KEY
),
true
)
def sessionTokenPair(implicit request: RequestHeader): Option[RequestToken] = {
for {
token <- request.session.get("token")
secret <- request.session.get("secret")
} yield {
RequestToken(token, secret)
}
}
def authenticate = Action { (request: Request[AnyContent]) =>
request
.getQueryString("oauth_verifier")
.map { verifier =>
val tokenPair = sessionTokenPair(request).get
// We got the verifier; now get the access token, store it and back to index
oauth.retrieveAccessToken(tokenPair, verifier) match {
case Right(t) => {
// We received the authorized tokens in the OAuth object - store it before we proceed
Redirect(routes.Application.index).withSession("token" -> t.token, "secret" -> t.secret)
}
case Left(e) => throw e
}
}
.getOrElse(oauth.retrieveRequestToken("https://localhost:9000/auth") match {
case Right(t) => {
// We received the unauthorized tokens in the OAuth object - store it before we proceed
Redirect(oauth.redirectUrl(t.token)).withSession("token" -> t.token, "secret" -> t.secret)
}
case Left(e) => throw e
})
}
实现流程后,可以通过通过 WS 签署请求来获取时间线
def timeline = Action.async { implicit request: Request[AnyContent] =>
sessionTokenPair match {
case Some(credentials) => {
wsClient
.url("https://api.twitter.com/1.1/statuses/home_timeline.json")
.sign(OAuthCalculator(KEY, credentials))
.get()
.map(result => Ok(result.json))
}
case _ => Future.successful(Redirect(routes.Application.authenticate))
}
}
注意:OAuth 不会提供任何针对 MITM 攻击的保护。此示例显示了存储在会话 cookie 中的 OAuth 令牌和密钥 - 为了获得最佳安全性,请始终使用 HTTPS,并定义
play.http.session.cookie.secure=true
。
下一步:与 Pekko 集成
发现此文档中的错误?此页面的源代码可以在 此处 找到。阅读完 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?请访问 我们的社区论坛,与社区开始对话。