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

查看:67
本文介绍了“需要登录";通过OAuth 2.0使用服务帐户调用v3 Google日历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).

第二个问题是我已经编写了一些代码来执行此操作,但是当我调用执行方法Calendar提要时,我返回了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.我已经打开了帐户中的Calendar 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.

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

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, 错误":[{ "domain":"global", "location":授权", "locationType":"header", "message":需要登录", "reason":必填" }], "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.

在此先感谢您的帮助.

Justin

推荐答案

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

}

在Google自己的代码示例中,他们第一次进行了准备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日历API时出现401未经授权的消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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