§OAuth
OAuth 是一種發布和與受保護資料互動的簡單方式。它也是一種更安全且更穩妥的方式,讓其他人授予您存取權。例如,它可用於存取您使用者在 Twitter 上的資料。
OAuth 有兩個非常不同的版本:OAuth 1.0 和 OAuth 2.0。版本 2 夠簡單,可以輕鬆地實作,不需要函式庫或輔助程式,因此 Play 只提供對 OAuth 1.0 的支援。
§用法
要使用 OAuth,請先將 ws
新增到您的 build.sbt
檔案
libraryDependencies ++= Seq(
javaWs
)
§所需資訊
OAuth 要求您向服務供應商註冊您的應用程式。務必檢查您提供的回呼網址,因為如果服務供應商不接受,可能會拒絕您的呼叫。在本地端工作時,您可以使用 /etc/hosts
在您的本地機器上偽造一個網域。
服務供應商會提供給您
- 應用程式 ID
- 金鑰
- 要求權杖網址
- 取用權杖網址
- 授權網址
§驗證流程
大部分的流程都將由 Play 函式庫完成。
- 從伺服器取得要求權杖(在伺服器對伺服器的呼叫中)
- 將使用者重新導向到服務供應商,使用者會在該處授予您的應用程式使用其資料的權限
- 服務供應商會將使用者重新導向回來,並提供給您一個 /驗證器/
- 使用該驗證器,將 /要求權杖/ 兌換成 /取用權杖/(伺服器對伺服器的呼叫)
現在可以將 /取用權杖/ 傳遞給任何呼叫,以存取受保護的資料。
有關 OAuth 流程的更多詳細資訊,請參閱 OAuth 聖經。
§範例
conf/routes
:
GET /twitter/homeTimeline controllers.Twitter.homeTimeline(request: Request)
GET /twitter/auth controllers.Twitter.auth(request: Request)
控制器
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.inject.Inject;
import play.libs.oauth.OAuth;
import play.libs.oauth.OAuth.ConsumerKey;
import play.libs.oauth.OAuth.OAuthCalculator;
import play.libs.oauth.OAuth.RequestToken;
import play.libs.oauth.OAuth.ServiceInfo;
import play.libs.ws.WSClient;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Result;
public class Twitter extends Controller {
static final ConsumerKey KEY = new ConsumerKey("...", "...");
private static final ServiceInfo SERVICE_INFO =
new ServiceInfo(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
"https://api.twitter.com/oauth/authorize",
KEY);
private static final OAuth TWITTER = new OAuth(SERVICE_INFO);
private final WSClient ws;
@Inject
public Twitter(WSClient ws) {
this.ws = ws;
}
public CompletionStage<Result> homeTimeline(Http.Request request) {
Optional<RequestToken> sessionTokenPair = getSessionTokenPair(request);
if (sessionTokenPair.isPresent()) {
return ws.url("https://api.twitter.com/1.1/statuses/home_timeline.json")
.sign(new OAuthCalculator(Twitter.KEY, sessionTokenPair.get()))
.get()
.thenApply(result -> ok(result.asJson()));
}
return CompletableFuture.completedFuture(redirect(routes.Twitter.auth()));
}
public Result auth(Http.Request request) {
Optional<String> verifier = request.queryString("oauth_verifier");
Result result =
verifier
.filter(s -> !s.isEmpty())
.map(
s -> {
RequestToken requestToken = getSessionTokenPair(request).get();
RequestToken accessToken = TWITTER.retrieveAccessToken(requestToken, s);
return redirect(routes.Twitter.homeTimeline())
.addingToSession(request, "token", accessToken.token)
.addingToSession(request, "secret", accessToken.secret);
})
.orElseGet(
() -> {
String url = routes.Twitter.auth().absoluteURL(request);
RequestToken requestToken = TWITTER.retrieveRequestToken(url);
return redirect(TWITTER.redirectUrl(requestToken.token))
.addingToSession(request, "token", requestToken.token)
.addingToSession(request, "secret", requestToken.secret);
});
return result;
}
private Optional<RequestToken> getSessionTokenPair(Http.Request request) {
return request
.session()
.get("token")
.map(token -> new RequestToken(token, request.session().get("secret").get()));
}
}
注意: OAuth 無法提供任何防護,以防止 中間人攻擊。此範例顯示儲存在會話 Cookie 中的 OAuth 權杖和金鑰 - 為了最佳安全性,請務必使用 HTTPS,並定義
play.http.session.secure=true
。
下一步:與 Pekko 整合
在此文件發現錯誤?此頁面的原始碼可在此處找到 here。在閱讀 文件指南 後,請隨時貢獻一個 pull request。有問題或建議要分享嗎?請前往 我們的社群論壇 與社群開始對話。