【问题标题】:Java Google Contacts API Access Service Account AuthenticationJava Google Contacts API 访问服务帐号认证
【发布时间】:2015-04-30 11:56:26
【问题描述】:

我正在尝试访问Googles Contacts API,但我的尝试在获得授权时已经失败。从其他(网络)语言,我习惯了 APIConsole 和公共 API 密钥(授权)。

GoogleCredential credential = new GoogleCredential().setAccessToken("<<PublicAPIKey>>");
System.out.println(credential.refreshToken());          // false

这样我无法刷新令牌并且不确定是否将公钥用作accesstoken...相反,我尝试了service account

private static final String USER_ACCOUNT_EMAIL = "xy@gmail.com";
private static final String SERVICE_ACCOUNT_EMAIL = "xy@developer.gserviceaccount.com";
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "xy.p12";

public App() {
    Set<String> scopes = new HashSet<String>();
    scopes.add("https://www.google.com/m8/feeds");

    try {
        GoogleCredential credential = new GoogleCredential.Builder()
            .setTransport(new NetHttpTransport())
            .setJsonFactory(new JacksonFactory())
            .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
            .setServiceAccountScopes(scopes)
            .setServiceAccountUser(USER_ACCOUNT_EMAIL)
            .setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
            .build();

        System.out.println(credential.refreshToken());
        //System.out.println(credential.getAccessToken());
    } catch (GeneralSecurityException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

这是我的例外:

com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized
        at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
        at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
        at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
        at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:384)
        at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
        at App.<init>(App.java:50)
        at App.main(App.java:29)

感谢您的提示!

【问题讨论】:

  • 您确定服务帐户有联系人吗?
  • 不是真的,但over oauth1 like here 不是替代品 - 它会在 6 天后关闭...而且我不了解公共 API 访问的机制。
  • 最糟糕的解决方法:如果我向另一个 API(例如 Google Plus)发出请求,第一个请求会返回一个有效的访问令牌。从那里我可以通过setOAuth2Credentials() 访问联系人API。不开心:)
  • 将其发布为答案。我喜欢 hacks 可能有一天会有用。背景:联系人 API 是一个旧的 gdata API,非常基础且很痛苦。 Google plus 是一个发现 API,使用起来更容易。

标签: java google-api authorization google-oauth google-api-java-client


【解决方案1】:

无需调用setServiceAccountUser(),我的代码就可以正常工作。但是你只会有一个impersonated account (service_account_mail) 而不是你的个人联系人。

“401 Unauthorized”异常的另一个可能来源是离开 credential.refreshToken()。调用是将访问代码写入引用所必需的。

在完成的课下:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.gdata.client.contacts.ContactsService;

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

public class Connector {

  private static ContactsService contactService = null;
  private static HttpTransport httpTransport;

  private static final String APPLICATION_NAME = "Your-App/1.0";
  private static final String SERVICE_ACCOUNT_EMAIL = "xy@developer.gserviceaccount.com";

  private Connector() {
    // explicit private no-args constructor
  }

  public static ContactsService getInstance() {
    if (contactService == null) {
      try {
        contactService = connect();

      } catch (GeneralSecurityException | IOException e) {
        e.printStackTrace();
      }
    }

    return contactService;
  }

  private static ContactsService connect() throws GeneralSecurityException, IOException {
    httpTransport = GoogleNetHttpTransport.newTrustedTransport();

    // @formatter:off
    GoogleCredential credential = new GoogleCredential.Builder()
                                            .setTransport(httpTransport)
                                            .setJsonFactory(JacksonFactory.getDefaultInstance())
                                            .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                                            .setServiceAccountScopes(Collections.singleton("https://www.google.com/m8/feeds"))
                                            .setServiceAccountPrivateKeyFromP12File(new File("key.p12"))
                                            .build();
    // @formatter:on

    if (!credential.refreshToken()) {
      throw new RuntimeException("Failed OAuth to refresh the token");
    }

    ContactsService myService = new ContactsService(APPLICATION_NAME);
    myService.setOAuth2Credentials(credential);
    return myService;
  }

}

【讨论】:

  • 但是如果您想要个人帐户而不是服务帐户怎么办?
  • 嘿@StephanCelis 试试这个作为一个未经测试的假设 api 如何与个人帐户一起工作。将连接功能替换为:private static ContactsService connect(String uname, String pw) throws GeneralSecurityException, IOException { contactService = new ContactsService(APPLICATION_NAME); try { contactService.setUserCredentials(uname, pw); } catch (AuthenticationException exception) { exception.printStackTrace(); } return myService; } 不要忘记启用less secure apps
猜你喜欢
  • 1970-01-01
  • 2015-08-26
  • 2015-06-28
  • 2021-01-17
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多