§OAuth
OAuth 是一種公開和互動受保護資料的簡單方式。它也是人們授予您存取權限更安全的方法。例如,它可用於存取您使用者在 Twitter 上的資料。
OAuth 有兩個截然不同的版本:OAuth 1.0 和 OAuth 2.0。版本 2 夠簡單,可以輕鬆實作,無需使用函式庫或輔助程式,因此 Play 僅提供對 OAuth 1.0 的支援。
§使用方式
要使用 OAuth,請先將 ws
新增到 build.sbt
檔案
libraryDependencies ++= Seq(
ws
)
§所需資訊
OAuth 需要您向服務供應商註冊您的應用程式。務必檢查您提供的回呼網址,因為如果服務供應商的網址與您提供的網址不符,服務供應商可能會拒絕您的呼叫。在本地端工作時,您可以使用 /etc/hosts
在您的本地端機器上偽造一個網域。
服務供應商會提供給您
- 應用程式 ID
- 金鑰
- 要求權杖網址
- 存取權杖網址
- 授權網址
§驗證流程
大部分的流程都將由 Play 函式庫完成。
- 從伺服器取得要求權杖(在伺服器對伺服器的呼叫中)
- 將使用者重新導向到服務供應商,使用者將在那裡授予您的應用程式使用其資料的權限
- 服務供應商將重新導向使用者,並提供給您一個 /驗證者/
- 使用該驗證者,將 /要求權杖/ 交換成 /存取權杖/(伺服器對伺服器的呼叫)
現在,/存取權杖/ 可以傳遞給任何呼叫,以存取受保護的資料。
可以在 OAuth 聖經 中找到有關 OAuth 程序流程的更多詳細資訊。
§範例
要在控制器中實作流程,請定義金鑰和消費者金鑰,並擷取權杖和金鑰
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://127.0.0.1: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 整合
在這個文件裡發現錯誤嗎?這個頁面的原始碼可以 在此找到。在閱讀完 文件指南 後,請隨時提交拉取請求。有任何問題或建議要分享嗎?請前往 我們的社群論壇 與社群展開討論。