【问题标题】:OAuth - Invalid token: Request token used when not allowedOAuth - 无效令牌:请求令牌在不允许时使用
【发布时间】:2012-05-01 20:00:38
【问题描述】:

我正在尝试使用 OAuth 2.0 访问 Google 的 Documents List API 3.0,但遇到了 401 错误问题。

用户接受后,我的代码如下:

GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(CLIENT_ID);
oauthParameters.setOAuthConsumerSecret(CLIENT_SECRET);
oauthParameters.setOAuthToken(token);
oauthParameters.setOAuthTokenSecret(tokenSecret);
oauthParameters.setScope("https://docs.google.com/feeds/");

service = new DocsService("myapp");
service.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());

DocumentListFeed feed = service.getFeed(new URL("https://docs.google.com/feeds/default/private/full/?v=3"), DocumentListFeed.class);

然后,在最后一行 -getFeed()- 抛出异常:

com.google.gdata.util.AuthenticationException: Token invalid - Invalid token: Request token used when not allowed.
<HTML>
<HEAD>
<TITLE>Token invalid - Invalid token: Request token used when not allowed.</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Token invalid - Invalid token: Request token used when not allowed.</H1>
<H2>Error 401</H2>
</BODY>
</HTML>

发生了什么事?在静态主测试类上的工作就像一个魅力,但是当我在服务器上运行它时,这条线不再工作了。有什么想法吗?


已解决

需要通过这种方式检索访问令牌,使用 GoogleOAuthHelper,而不是直接使用 GoogleOAuthParameters:

String accessToken = oauthHelper.getAccessToken(oauthParameters);

【问题讨论】:

  • 你能把你的解决方案放在一个答案中并接受这个答案吗?这样,问题就被标记为已解决,如果有人(出于任何原因)访问此帖子,将很容易找到答案。

标签: java oauth google-docs-api


【解决方案1】:

您使用的不是 OAuth 2.0,而是使用 HMAC-SHA1 作为签名方法的 OAuth 1.0。要使用 OAuth 2.0,您至少需要 gdata-java-client 库的 1.47.0 版和 google-oauth-java-client 库的 1.8.0-beta 版。

使用 google-api-java-client 库提供帮助类来处理 Google 的 OAuth 2.0 实现。

要检索 OAuth 2.0 凭据,您可以使用以下代码 sn-p:

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

public class MyClass {

  // Retrieve the CLIENT_ID and CLIENT_SECRET from an APIs Console project:
  //     https://code.google.com/apis/console
  static String CLIENT_ID = "<YOUR_CLIENT_ID>";
  static String CLIENT_SECRET = "<YOUR_CLIENT_SECRET>";
  // Change the REDIRECT_URI value to your registered redirect URI for web
  // applications.
  static String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
  // Add other requested scopes.
  static List<String> SCOPES = Arrays.asList("https://docs.google.com/feeds");

  /**
   * Retrieve OAuth 2.0 credentials.
   * 
   * @return OAuth 2.0 Credential instance.
   */
  static Credential getCredentials() throws IOException {
    HttpTransport transport = new NetHttpTransport();
    JacksonFactory jsonFactory = new JacksonFactory();

    // Step 1: Authorize -->
    String authorizationUrl =
        new GoogleAuthorizationCodeRequestUrl(CLIENT_ID, REDIRECT_URI, SCOPES).build();

    // Point or redirect your user to the authorizationUrl.
    System.out.println("Go to the following link in your browser:");
    System.out.println(authorizationUrl);

    // Read the authorization code from the standard input stream.
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    System.out.println("What is the authorization code?");
    String code = in.readLine();
    // End of Step 1 <--

    // Step 2: Exchange -->
    GoogleTokenResponse response =
        new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory, CLIENT_ID, CLIENT_SECRET,
            code, REDIRECT_URI).execute();
    // End of Step 2 <--

    // Build a new GoogleCredential instance and return it.
    return new GoogleCredential.Builder().setClientSecrets(CLIENT_ID, CLIENT_SECRET)
        .setJsonFactory(jsonFactory).setTransport(transport).build()
        .setAccessToken(response.getAccessToken()).setRefreshToken(response.getRefreshToken());
  }

  // …
}

拥有 OAuth 2.0 凭证后,您可以按如下方式授权服务对象:

// ...
import com.google.api.client.auth.oauth2.Credential;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.util.ServiceException;
// ...
import java.io.IOException;
import java.net.URL;
// ...

public class MyClass {
  // …

  /**
   * Print document entries using the provided authorized DocsService.
   * 
   * @param credential OAuth 2.0 credential to use to authorize the requests.
   * @throws IOException
   * @throws ServiceException
   */
  static void printDocuments(Credential credential) throws IOException, ServiceException {
    // Instantiate and authorize a new DocsService object.
    DocsService service = new DocsService("<YOUR_APPLICATION_NAME>");
    service.setOAuth2Credentials(credential);

    // Send a request to the Documents List API to retrieve document entries.
    URL feedUri = new URL("https://docs.google.com/feeds/default/private/full/");
    DocumentListFeed feed = service.getFeed(feedUri, DocumentListFeed.class);

    for (DocumentListEntry entry : feed.getEntries()) {
      System.out.println("Title: " + entry.getTitle().getPlainText());
    }
  }

  // ...
}

CLIENT_IDCLIENT_SECRET 可以从APIs Console 中检索到,REDIRECT_URI 必须与已在您的 API 项目中注册的匹配。

【讨论】:

  • 谢谢。你是对的。已修复以使用 OAuth2 运行。但是你的代码有错误,这句话是倒过来的:.setRefreshToken(response.getAccessToken()).setAccessToken(response.getRefreshToken());
  • 谢谢,我修复了样本 :-)
  • 你能提供这个jar google-api-java-client 的maven依赖的链接吗?
  • There你去!
【解决方案2】:

以下是向 GData 服务添加 OAuth2.0 令牌的方法:

SpreadsheetService service = new SpreadsheetService("MySpreadsheetIntegration-v1");

service.setOAuth2Credentials(new Credential(BearerToken
    .authorizationHeaderAccessMethod())
    .setFromTokenResponse(new TokenResponse().setAccessToken(mToken)));

确保导入所有必要的库(很多)。

Android 令牌应使用 Google Play Services OAuth 机制获取:

String token = GoogleAuthUtil.getToken(String email, String scopes);

【讨论】:

  • 这个答案完美地补充了投票最多的答案...@zavidovych 您是否考虑过编辑另一个答案以丰富它?
猜你喜欢
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 2017-03-14
  • 2014-08-29
  • 1970-01-01
  • 2012-06-22
相关资源
最近更新 更多