OAuth – 无效令牌:不允许时使用请求令牌

我正在尝试使用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() – 抛出exception:

 com.google.gdata.util.AuthenticationException: Token invalid - Invalid token: Request token used when not allowed.   Token invalid - Invalid token: Request token used when not allowed.   

Token invalid - Invalid token: Request token used when not allowed.

Error 401

这是怎么回事? 在静态主测试类上工作就像一个魅力,但当我在服务器上运行它时,这条线不再起作用了。 任何想法?


解决了

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

 String accessToken = oauthHelper.getAccessToken(oauthParameters); 

您没有使用OAuth 2.0,而是使用OAAC 1.0和HMAC-SHA1作为签名方法。 要使用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凭据,您可以使用以下代码段:

 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 = ""; static String 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 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(""); 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()); } } // ... } 

可以从API控制台检索CLIENT_IDCLIENT_SECRETREDIRECT_URI必须与已在API项目中注册的REDIRECT_URI匹配。

以下是如何将OAuth2.0令牌添加到GData服务:

 SpreadsheetService service = new SpreadsheetService("MySpreadsheetIntegration-v1"); service.setOAuth2Credentials(new Credential(BearerToken .authorizationHeaderAccessMethod()) .setFromTokenResponse(new TokenResponse().setAccessToken(mToken))); 

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

在Android上,令牌应使用Google Play服务OAuth机制获取:

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