“需要登录"通过 OAuth 2.0 使用服务帐户调用 v3 Google Calendar API 时出现 401 未经授权的消息 [英] "Login Required" 401 Unauthorized message when calling the v3 Google Calendar API using a Service Account via OAuth 2.0

查看:16
本文介绍了“需要登录"通过 OAuth 2.0 使用服务帐户调用 v3 Google Calendar API 时出现 401 未经授权的消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,让我解释一下我想要做什么,因为这是一个由两部分组成的问题.

First, let me explain what I am trying to do, as this is a two part question.

我正在构建一个 JAX-RS 服务,该服务通过 OAuth2 对 Google 帐户进行内部身份验证,因此它可以访问和操作 Google 日历.该服务将由网站 (Joomla) 调用,该网站将允许登录该网站的用户在日历事件中注册他们的电子邮件地址,以便在事件临近时他们可以收到电子邮件通知.这些用户不了解底层 Google 帐户.

I am building a JAX-RS service that internally authenticates with a Google account via OAuth2, so it can access and manipulate a Google calendar. This service will be called by a web site (Joomla), which will allow users that login into the site to register their email address with calendar events so they can get email notifications when the events are near. These users have no knowledge of the underlying Google account.

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

So my first question, is using Service Account authentication the right thing? Looking at the Google docs, its the only use case that caters for non-human authentication (so server to server authentication).

第二个问题是我已经编写了一些代码来执行此操作,但是当我调用日历提要的执行方法时,我得到了 401/Unauthorized 响应,并返回以下错误.此代码取自 Google 示例.

The second problem is that I have written some code to do this, but I get back a 401/Unauthorized response back the following error back when I call the execute method the Calendar feed. This code was lifted from the Google samples.

我使用的是 Google Calendar API 的 v3-rev3-1.5.0-beta.我已在帐户中打开日历 API,并创建并下载了一个私钥,该私钥在下面的代码中使用.

I am using v3-rev3-1.5.0-beta of the the Google Calendar API. I have turned on the Calendar API in the account, and created and downloaded a private key, that is used in the code below.

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

I am calling the code below in Eclipse locally, not from a web server.

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

So the first call I make is to get back a credential object (Id's obfuscated with X's):

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();

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

The next step is to then call the Calendar API, like so (no other code called in between):

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

 CalendarList feed = calendar.calendarList().list().execute();

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

The call to list().execute() results in the following error:

com.google.api.client.googleapis.json.GoogleJsonResponseException:401 未经授权{代码":401,错误":[{域":全局","location" : "授权",位置类型":标题","message": "需要登录",原因":必须"}],"message" : "需要登录"}在 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)在 com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:112)在 com.google.api.services.calendar.Calendar$CalendarList$List.execute(Calendar.java:510)在 uk.org.reigatepriorybowmen.Service.registerEmailForAllCalendarEvents(Service.java:55)在 uk.org.reigatepriorybowmen.Service.main(Service.java:74)

com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized { "code" : 401, "errors" : [ { "domain" : "global", "location" : "Authorization", "locationType" : "header", "message" : "Login Required", "reason" : "required" } ], "message" : "Login Required" } at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:159) at com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:187) at com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:115) at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:112) at 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)

服务帐号设置如下:

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

So, what am I doing wrong?! I have spent hours Googling around looking for solutions so this is my last hope.

非常感谢您的帮助.

贾斯汀

推荐答案

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

As for the 401, it seems some oddity with Google's API. I find the first time I run my app in a while, and then at seemingly random intervals hours spread apart, I always get a 401. On the second or third round it actually logs in.

Google 的 Task API 示例代码中甚至考虑到了这种行为 此处.

The behavior is even accounted for in Google's Task API sample code here.

注意这个代码:

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);

}

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

In Google's own code sample they have made provision for a first time 401. It might be some special security issue that needs to be handled in code.

这篇关于“需要登录"通过 OAuth 2.0 使用服务帐户调用 v3 Google Calendar API 时出现 401 未经授权的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆