文件

§OAuth

OAuth 是一種發布和與受保護資料互動的簡單方式。它也是一種更安全且更穩妥的方式,讓其他人授予您存取權。例如,它可用於存取您使用者在 Twitter 上的資料。

OAuth 有兩個非常不同的版本:OAuth 1.0OAuth 2.0。版本 2 夠簡單,可以輕鬆地實作,不需要函式庫或輔助程式,因此 Play 只提供對 OAuth 1.0 的支援。

§用法

要使用 OAuth,請先將 ws 新增到您的 build.sbt 檔案

libraryDependencies ++= Seq(
  javaWs
)

§所需資訊

OAuth 要求您向服務供應商註冊您的應用程式。務必檢查您提供的回呼網址,因為如果服務供應商不接受,可能會拒絕您的呼叫。在本地端工作時,您可以使用 /etc/hosts 在您的本地機器上偽造一個網域。

服務供應商會提供給您

§驗證流程

大部分的流程都將由 Play 函式庫完成。

  1. 從伺服器取得要求權杖(在伺服器對伺服器的呼叫中)
  2. 將使用者重新導向到服務供應商,使用者會在該處授予您的應用程式使用其資料的權限
  3. 服務供應商會將使用者重新導向回來,並提供給您一個 /驗證器/
  4. 使用該驗證器,將 /要求權杖/ 兌換成 /取用權杖/(伺服器對伺服器的呼叫)

現在可以將 /取用權杖/ 傳遞給任何呼叫,以存取受保護的資料。

有關 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。有問題或建議要分享嗎?請前往 我們的社群論壇 與社群開始對話。