如何使用 Java 访问 Google Calendar REST API v3

我正在做一个项目,我必须使用REST和使用Java访问一组Google日历。

该程序位于私人非Google服务器上,定期(通过cron作业)连接到Google帐户,获取链接到该帐户的日历列表,获取每个日历上个月的事件,并返回包含所有信息的XML文件。该程序应该能够在没有任何用户输入的情况下执行和访问日历。目前,该项目指定日历将仅被读取,而不是修改(因此将只进行GET / LIST调用)。

我已经浏览了Google文档,并使用客户端库查看了示例代码,几乎所有给出的示例都需要OAuth 2.0用户同意才能访问日历API。甚至 REST API 文档页面也要求您激活 OAuth 2.0 以返回请求的信息(否则返回 HTTP 40X 错误代码和包含错误状态和消息的 JSON 文件)。

我如何连接到Google Calendar REST API来获取我需要的信息,一切都是通过REST调用完成的,并且在执行时不需要用户同意?

还是我把事情过于复杂化,只需要在Google Cloud Console的重新注册的应用程序部分找到的“服务器密钥”?
或者我需要同时使用 OAuth 和开发人员密钥?(我发现有人在标题为“Google Calendar API v3硬编码凭据”的问题下提到了它;但是,这个问题和解决方案是针对PHP的,我不知道在Java中是否有可能或有必要类似的东西)。

  • 我确实看到了使用服务帐户创建JWT的可能性(使用Google云控制台,注册为Web应用程序,并且它在“证书”下),但我没有找到如何将其与Java程序的REST调用结合使用。
  • 以下链接(http://aleksz-programming.blogspot.be/2012/11/google-calendar-api.html)说可以通过“Web服务器应用程序”或“已安装的应用程序”访问信息,但没有详细说明。但是,在Google OAuth 2.0文档页面上,“Web服务器应用程序”部分仍然需要用户输入和同意。哪个是真的?
  • 我还找到了这个页面(https://developers.google.com/accounts/docs/OAuth2Login),但未能看到如何在不使用用户同意页面的情况下使用它。
  • 我确实看到了一些对“双腿OAuth”的引用。但似乎这不是OAuth 2.0,而是版本1正在做事情。它是我的项目的可能解决方案吗?如果是这样,我需要从Google Cloud Console获得哪些信息才能使其正常工作?

我希望我已经提供了足够的信息来说明我正在寻找什么,并且到目前为止还没有涵盖这个问题。我确实研究了它,但没有找到任何与我正在寻找的东西足够接近的东西。

我无法发布超过2个链接(缺乏声誉),但确实查看了Google Calendar v3 REST API,以及指定创建JWT的页面。


答案 1

如果您只需要访问一组特定的日历,我会创建一个服务帐户,并与该帐户共享必要的日历。

为此,请执行以下操作:

  1. 在此云控制台中创建一个“服务帐户”(可在“Web 应用程序”/“证书”下找到)。
  2. 下载私钥并存储在安全的地方。
  3. 记下与服务帐户关联的电子邮件地址。
  4. 使用此电子邮件地址共享(通过日历用户界面)任何必要的日历。
  5. 安装 Google API Java Client 库(https://developers.google.com/api-client-library/java/apis/)。

然后,您应该能够使用以下代码:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.json.gson.GsonFactory;
import java.io.File;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import java.util.Arrays;
import com.google.api.services.calendar.Calendar;

GoogleCredential credentials = new GoogleCredential.Builder().setTransport(GoogleNetHttpTransport.newTrustedTransport())
  .setJsonFactory(new GsonFactory())
  .setServiceAccountId("<service account email address>@developer.gserviceaccount.com")
  .setServiceAccountScopes(Arrays.asList("https://www.googleapis.com/auth/calendar.readonly"))
  .setServiceAccountPrivateKeyFromP12File(new File("<private key for service account in P12 format>-privatekey.p12"))
.build();
Calendar client = new Calendar.Builder(GoogleNetHttpTransport.newTrustedTransport(), new GsonFactory(), credentials).build();
client.<do calendar stuff>.execute();

如果您是网域管理员,需要在未经个别用户同意的情况下访问属于您网域的所有 Google Apps 帐号的日历,则无需执行上述步骤 4:

  1. 记下与服务帐户关联的客户端 ID。这可以在client_secrets.json文件中找到 - 通常采用 1234.apps.googleusercontent.com 的形式。
  2. 授权此客户端代表组织中的用户发出请求。有关步骤,请参阅 https://support.google.com/a/answer/162106?hl=en - 使用稍后要请求的任何作用域。

您现在应该能够编写如下代码:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.json.gson.GsonFactory;
import java.io.File;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import java.util.Arrays;
import com.google.api.services.calendar.Calendar;

GoogleCredential credentials = new GoogleCredential.Builder().setTransport(GoogleNetHttpTransport.newTrustedTransport())
  .setJsonFactory(new GsonFactory())
  .setServiceAccountId("<service account email address>@developer.gserviceaccount.com")
  .setServiceAccountScopes(Arrays.asList("https://www.googleapis.com/auth/calendar"))
  .setServiceAccountPrivateKeyFromP12File(new File("<private key for service account in P12 format>-privatekey.p12"))
  .setServiceAccountUser("<domain user whose data you need>@yourdomain.com")
.build();
Calendar client = new Calendar.Builder(GoogleNetHttpTransport.newTrustedTransport(), new GsonFactory(), credentials).build();
client.<do calendar stuff as that user>()

答案 2

除了@aeijdenberg的答案中提到的步骤之外,服务帐户现在还需要通过 CalendarList.insert 将其添加到其 CalendarList 中,从而明确接受共享日历。看:

服务帐户不再接受自动共享的日历 [148804709] https://issuetracker.google.com/issues/148804709


推荐