【问题标题】:Refresh Access Token with OAuth 2.0 Google App Engine使用 OAuth 2.0 Google App Engine 刷新访问令牌
【发布时间】:2014-07-30 11:06:41
【问题描述】:

鉴于已经从第一个授权流程中获取了刷新令牌,我想实现自动刷新方法来获取新的访问令牌。

我应该调用哪个方法或方法列表来做到这一点?我正在为 Web 应用程序使用 Java 和 OAuth 2.0。鉴于OAuth 2.0 WebApplication,我应该在这段代码中添加什么才能让一切正常工作?

【问题讨论】:

标签: java google-app-engine oauth oauth-2.0 google-oauth


【解决方案1】:

您在问题中提供的链接使用Google APIs Client Library for Java 实现了 Google OAuth 2.0 授权。和 这个库已经实现了刷新访问令牌的功能。

所以你需要在这个库中使用Class GoogleRefreshTokenRequest

此类是 OAuth 2.0 请求的 Google 特定实现,用于使用 Refreshing an Access Token 中指定的刷新令牌刷新访问令牌。

而且它的java doc也给出了一个示例用法:

static void refreshAccessToken() throws IOException {
try {
  TokenResponse response =
      new GoogleRefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(),
          "tGzv3JOkF0XG5Qx2TlKWIA", "s6BhdRkqt3", "7Fjfp0ZBr1KtDRbnfVdmIw").execute();
  System.out.println("Access token: " + response.getAccessToken());
} catch (TokenResponseException e) {
  if (e.getDetails() != null) {
    System.err.println("Error: " + e.getDetails().getError());
    if (e.getDetails().getErrorDescription() != null) {
      System.err.println(e.getDetails().getErrorDescription());
    }
    if (e.getDetails().getErrorUri() != null) {
      System.err.println(e.getDetails().getErrorUri());
    }
  } else {
    System.err.println(e.getMessage());
  }
}

}

这是another usage,你可以参考。

您可以在CredentialManager.java中添加如下代码,当需要刷新token时,调用该方法。

public Credential refreshAccessToken(String refreshToken, String clientId, String clientSecret) throws IOException {
try {
  TokenResponse response =
  new GoogleRefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(),
      refreshToken, clientId, clientSecret).execute();
  System.out.println("Access token: " + response.getAccessToken());
  return buildEmpty().setAccessToken(response.getAccessToken());
} catch (TokenResponseException e) {
  if (e.getDetails() != null) {
    System.err.println("Error: " + e.getDetails().getError());
    if (e.getDetails().getErrorDescription() != null) {
      System.err.println(e.getDetails().getErrorDescription());
    }
    if (e.getDetails().getErrorUri() != null) {
      System.err.println(e.getDetails().getErrorUri());
    }
  } else {
    System.err.println(e.getMessage());
  }
}

另一种方法是使用 DataStoreCredentialRefreshListener

使用 GoogleCredential 访问受保护的资源。过期的访问令牌将使用刷新令牌(如果适用)自动刷新。确保使用DataStoreCredentialRefreshListener 并使用GoogleCredential.Builder.addRefreshListener(CredentialRefreshListener) 将其设置为凭据。

【讨论】:

  • 只是调用 refreshAccessToken() 方法,我的凭据会自动刷新吗?或者在获得 TokenResponse 后,我必须构建并清空凭据,添加/替换新的访问令牌并从 AppEngineCredentialStore 重新加载凭据?因为我使用developers.google.com/drive/web/examples/java (github.com/googledrive/dredit/blob/master/java/src/com/google/…) 开启了另一个示例,即 DrEdit(Java 版本)
  • 是的,调用此方法不会自动更新您的凭证,您需要使用新令牌重置您的凭证。
  • 非常感谢!你救了我和其他许多人。我认为您甚至可以使用(作为返回): return buildEmpty().setFromTokenResponse(response);它也将起作用。我对么? :-)
  • @OwenCao 当我在课堂上使用第一个函数时,我得到了无法找到 TokenResponse 和 GoogleRefreshTokenRequest 的符号错误。你能告诉如何解决这个问题。我是否需要包含 jar 文件?
  • @Santhosh 是的,你需要 google-api-java-client,developers.google.com/api-client-library/java
【解决方案2】:
final GoogleCredential credential = new Builder()
        .setTransport(new NetHttpTransport())
        .setJsonFactory(new JacksonFactory())
        .setClientSecrets(OAuth2Provider.GOOGLE_CLIENT_ID, OAuth2Provider.GOOGLE_CLIENT_SECRET)
        .build()
        .setRefreshToken(refreshToken);

credential.refreshToken(); // do not forget to call

String newAccessToken = credential.getAccessToken();

然后你可以使用像UserTokens这样的对象:

public class UserTokens {

    public final String accessToken;
    public final String refreshToken;

    public UserTokens(String accessToken, String refreshToken) {
        this.accessToken = accessToken;
        this.refreshToken = refreshToken;
    }

}

...然后将其存储在数据库中:

TokenRepository tokenRepository = new PersistentTokenRepository();
tokenRepository.store(userTokens);

注意事项

  • OAuth2Provider 是我的自定义类,我在其中保留客户的 id秘密
  • TokenRepository 是一个自定义接口,具有 store()get()
  • PersistentTokenRepository是自定义上层的实现 您可以将令牌存储在 SQL 或 NoSQL 数据库中的接口,例如 GAE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-01
    • 2013-11-23
    • 1970-01-01
    • 2012-07-11
    • 2017-06-09
    • 2015-11-26
    • 2013-02-23
    • 2014-09-22
    相关资源
    最近更新 更多