"需要登录"401通过OAuth 2.0使用服务帐户呼叫v3 Google Calendar API时未经授权的消息

Jus*_*ips 18 google-calendar-api oauth-2.0 google-api-java-client google-oauth

首先,让我解释一下我要做的事情,因为这是一个两部分问题.

我建立在内部通过的OAuth2一个谷歌帐户验证一个JAX-RS的服务,所以它可以访问和操作谷歌日历.这项服务将通过一个网站(的Joomla),这将允许登录到网站的用户注册与日历事件他们的电子邮件地址,以便他们可以得到电子邮件通知当事件附近被调用.这些用户不了解底层Google帐户.

所以我的第一个问题是使用服务帐户身份验证是正确的吗?查看Google文档,它是唯一适合非人类身份验证的用例(因此服务器到服务器身份验证).

第二个问题是,我已经写了一些代码来做到这一点,但我拿回401 /未经授权的响应返回以下错误回来时,我调用execute方法日历饲料.此代码已从Google示例中取消.

我正在使用Google Calendar API的v3-rev3-1.5.0-beta.我已在帐户中启用了Calendar API,并创建并下载了私钥,该私钥在下面的代码中使用.

我在本地调用Eclipse中的代码,而不是从Web服务器调用.

所以我做的第一个调用是取回一个凭证对象(Id用X混淆):

private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
.
.
.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId("284XXXXXXXX@developer.gserviceaccount.com")
            .setServiceAccountScopes(CalendarScopes.CALENDAR)
            .setServiceAccountPrivateKeyFromP12File(new File("D:/3cd8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXd635e-privatekey.p12"))
            .build();
Run Code Online (Sandbox Code Playgroud)

下一步是调用Calendar API,就像这样(之间没有其他代码调用):

 Calendar calendar = Calendar.builder(HTTP_TRANSPORT, JSON_FACTORY)
        .setApplicationName("TestApp-Calendar/1.0").setHttpRequestInitializer(credential)
        .build();

 CalendarList feed = calendar.calendarList().list().execute();
Run Code Online (Sandbox Code Playgroud)

对list().execute()的调用导致以下错误:

com.google.api.client.googleapis.json.GoogleJsonResponseException:401 Unauthorized {"code":401,"errors":[{"domain":"global","location":"Authorization","locationType":"标题","消息":"需要登录","原因":"必需"}},"消息":"需要登录"} com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException. java:159)com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:187)com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:115) at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:112)at the com.google.api.services.calendar.Calendar $ CalendarList $ List.execute(Calendar.java:510)at uk .org.reigatepriorybowmen.Service.registerEmailForAllCalendarEvents(Service.java:55)at uk.org.reigatepriorybowmen.Service.main(Service.java:74)

服务帐户设置如下:

在此输入图像描述

那么,我做错了什么?!我花了几个小时在谷歌上寻找解决方案,所以这是我最后的希望.

非常感谢您的帮助.

贾斯汀

Eug*_*rwe 5

至于401,谷歌的API似乎有些奇怪.我发现我第一次运行我的应用程序,然后在看似随机的时间间隔小时分开,我总是得到401.在第二轮或第三轮它实际上登录.

该行为即使是在谷歌的任务API的示例代码占了这里.

请注意此代码:

void onRequestCompleted() {
received401 = false;
}

void handleGoogleException(IOException e) {
if (e instanceof GoogleJsonResponseException) {
  GoogleJsonResponseException exception = (GoogleJsonResponseException) e;
  if (exception.getStatusCode() == 401 && !received401) {
    received401 = true;
    accountManager.invalidateAuthToken(credential.getAccessToken());
    credential.setAccessToken(null);
    SharedPreferences.Editor editor2 = settings.edit();
    editor2.remove(PREF_AUTH_TOKEN);
    editor2.commit();
    gotAccount();
    return;
  }
}
Log.e(TAG, e.getMessage(), e);
Run Code Online (Sandbox Code Playgroud)

}

在谷歌自己的代码示例中,他们首次提供了401.可能需要在代码中处理一些特殊的安全问题.


Nic*_*ier 1

我认为您需要指定您试图模拟的用户。

您现在使用 ServiceAccount 的方式仅适用于访问与您的应用程序或服务帐户本身相关的数据。由于您希望访问 Google 日历数据,因此您必须是具有访问任何域用户数据权限的 Google Apps 域管理员 - 如果我的说法不正确,请告诉我。Google 日历数据属于用户,因此您需要指定要尝试模拟的用户。

要使用 Java 执行此操作,似乎您需要使用GoogleCredential.Builder#setServiceAccountUser(String)

请尝试:

GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId("284XXXXXXXX@developer.gserviceaccount.com")
        .setServiceAccountScopes(CalendarScopes.CALENDAR)
        .setServiceAccountPrivateKeyFromP12File(new File("/path/to/privatekey.p12"))
        .setServiceAccountUser("user@domain.com")
        .build();
Run Code Online (Sandbox Code Playgroud)

此外,在 API 项目中(从 API 控制台)创建服务帐户密钥后,您必须将该项目添加到 cPanel 中授权的第三方应用程序列表中。有关此内容的更多信息可以在此处找到。您需要使用的“客户端 ID”是绑定到服务帐户密钥的“客户端 ID”,如下所示<APP_ID>-<OTHER_KEY>.apps.googleusercontent.com