文档

§OAuth

OAuth 是一种简单的方式来发布和交互受保护的数据。它也是人们授予您访问权限的更安全、更可靠的方式。例如,它可以用于访问您用户在 Twitter 上的数据。

OAuth 有两个截然不同的版本:OAuth 1.0OAuth 2.0。版本 2 足够简单,可以在没有库或帮助程序的情况下轻松实现,因此 Play 仅提供对 OAuth 1.0 的支持。

§用法

要使用 OAuth,首先将 ws 添加到您的 build.sbt 文件中

libraryDependencies ++= Seq(
  javaWs
)

§所需信息

OAuth 要求您将应用程序注册到服务提供商。请务必检查您提供的回调 URL,因为如果它们不匹配,服务提供商可能会拒绝您的调用。在本地工作时,您可以使用 /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 集成


在此文档中发现错误?此页面的源代码可以在 此处 找到。阅读完 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?访问 我们的社区论坛 与社区开始对话。