5

我目前正在通过 OAuth 2.0 和所谓的服务帐户实现对 Google 通讯录的访问。服务帐户是为像“My.Name@gmail.com”这样的普通用户生成的。

生成 OAuth 2.0 凭据的代码是:

public static GoogleCredential getCredentials() throws GeneralSecurityException, IOException {
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId(SingleUserCredentials.SERVICE_ACCOUNT_EMAIL)
            .setServiceAccountScopes("https://www.google.com/m8/feeds")
            .setServiceAccountPrivateKeyFromP12File(new File(SingleUserCredentials.SERVICE_ACCOUNT_PKCS12_FILE_PATH))
            .build();
    credential.refreshToken();
    return credential;
}

然后我试图通过以下方式检索联系人:

    ContactsService myService = new ContactsService(
            "myApp");

    myService.setOAuth2Credentials(getCredentials());

    URL feedUrl = new URL("https://www.google.com/m8/feeds/contacts/default/full");
    Query myQuery = new Query(feedUrl);
    ContactFeed resultFeed = myService.query(myQuery, ContactFeed.class);
    // Print the results

    for (ContactEntry entry : resultFeed.getEntries()) {
        System.out.println(entry.getName().getFullName().getValue());
        System.out.println("Updated on: " + entry.getUpdated().toStringRfc822());
    }

问题是我没有从我的帐户中获得任何联系人。提要始终为空。没有错误。没有什么。

当通过相同的方法访问 Google Apps 托管域时,它运行良好。

我想知道在使用 p12 密钥文件和服务帐户时,Contacts Api 是否支持普通(又名@gmail.com)帐户的 OAuth 2.0。

4

3 回答 3

1

我自己也遇到了同样的问题。

我尝试了设置密钥时收到的电子邮件地址和域管理员的电子邮件地址。

当我使用密钥设置中的电子邮件时,我什么都没有收到——没有警告、没有异常,也没有数据。

当我使用域管理员的电子邮件地址时,我收到异常:

com.google.api.client.auth.oauth2.TokenResponseException: 400 OK
     [java] {
     [java]   "error" : "invalid_grant"
     [java] }
     [java] Feb 5, 2013 5:16:48 PM com.google.appengine.repackaged.org.apache.http.impl.client.DefaultRequestDirector handleResponse
     [java] WARNING: Authentication error: Unable to respond to any of these challenges: {}
     [java] Feb 5, 2013 5:16:48 PM com.google.apphosting.utils.jetty.JettyLogger warn
     [java] WARNING: /
     [java] java.lang.NullPointerException: No authentication header information

...

所以,我认为域管理员的电子邮件地址不是我需要的。

接下来,在找到此页面之前,我搜索了一段时间:

http://javadoc.google-api-java-client.googlecode.com/hg/1.13.2-beta/com/google/api/client/googleapis/auth/oauth2/GoogleCredential.html

我在那里看到了getServiceAccountUser()。该字段的描述是:

返回应用程序尝试在服务帐户流中模拟的用户的电子邮件地址,或者返回 null 表示无或不使用服务帐户流。

果然,有一个相应的 setServiceAccountUser (String) 接受您使用服务帐户模拟的用户的用户名(电子邮件地址)。

我将该字段设置为适当的值,并且能够继续。

回想起来,这一切都是有道理的——如果我不提供我正在尝试使用的帐户,我就无法删除该帐户的联系人。

于 2013-02-05T17:59:54.683 回答
0

目前无法使用服务帐户访问联系人,因为 Google APIs Console 的Google APIs Console不支持它。

另请参阅:服务帐户

其次,它仅适用于 Google 托管域,因为域的管理员必须通过以下过程授予对服务帐户的访问权限:

将域范围的权限委派给您的服务帐户

您现在创建的服务帐户需要被授予访问您要访问的 Google Apps 域的用户数据的权限。以下任务必须由 Google Apps 域的管理员执行:

  1. 转到您的 Google Apps 域的控制面板。该 URL 应类似于:“www.google.com/a/cpanel/mydomain.com”

  2. 转到高级工具... > 管理第三方 OAuth 客户端访问。

  3. 在客户端名称字段中输入服务帐户的客户端 ID。

  4. 在一个或多个 API 范围字段中,输入应授予您的应用程序访问权限的范围列表。

  5. 单击授权按钮。

于 2013-03-05T14:08:12.773 回答
0

我今天遇到了同样的错误,但现在已经放弃使用服务帐户,我认为联系人 API 目前不支持。因此,我将 Contacts API v3 与 OAuth 1.0 一起使用,并获得了预期的结果。

 ContactsService contactsService = new ContactsService(APPLICATION_NAME);
 contactsService.setUserCredentials(CLIENT_USERNAME, CLIENT_SECRET);

 URL contactFeedURL = new URL("https://www.google.com/m8/feeds/contacts/default/full");
 Query contactFeedQuery = new Query(contactFeedURL);

 ContactFeed contactFeed = contactsService.getFeed(contactFeedQuery, ContactFeed.class);
于 2013-03-26T01:39:25.673 回答