Вопрос по – «Требуется вход в систему» 401 Несанкционированное сообщение при вызове API Календаря Google v3 с использованием служебной учетной записи через OAuth 2.0

18

Во-первых, позвольте мне объяснить, что я пытаюсь сделать, так как это вопрос из двух частей.

Я создаю службу JAX-RS, которая выполняет внутреннюю аутентификацию с помощью учетной записи Google через OAuth2, чтобы она могла обращаться к календарю Google и манипулировать им. Эта служба будет вызываться веб-сайтом (Joomla), который позволит пользователям, которые входят на сайт, зарегистрировать свой адрес электронной почты в событиях календаря, чтобы они могли получать уведомления по электронной почте, когда события близки. Эти пользователи не знают основной учетной записи Google.

Итак, мой первый вопрос: правильно ли использовать аутентификацию учетной записи службы? Глядя на документы Google, это единственный вариант использования, который обслуживает нечеловеческую аутентификацию (то есть аутентификацию от сервера к серверу).

Вторая проблема заключается в том, что я написал некоторый код для этого, но я получаю ответ 401 / Несанкционированный ответ на следующую ошибку, когда я вызываю метод execute фидом Calendar. Этот код был взят из образцов Google.

Я использую v3-rev3-1.5.0-beta из API Календаря Google. Я включил Calendar API в учетной записи, создал и загрузил закрытый ключ, который используется в приведенном ниже коде.

Я вызываю код ниже в Eclipse локально, а не с веб-сервера.

Итак, первый вызов, который я делаю, - это вернуть объект учетных данных (идентификаторы обфусцированы с помощью X):

<code>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("[email protected]")
            .setServiceAccountScopes(CalendarScopes.CALENDAR)
            .setServiceAccountPrivateKeyFromP12File(new File("D:/3cd8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXd635e-privatekey.p12"))
            .build();
</code>

Следующим шагом является вызов API-интерфейса Calendar, например, так (никакой другой код не вызывается):

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

 CalendarList feed = calendar.calendarList().list().execute();
</code>

Вызов list (). Execute () приводит к следующей ошибке:

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)

Сервисная учетная запись настраивается следующим образом:

enter image description here

Итак, что я делаю не так ?! Я часами гулял в поисках решений, так что это моя последняя надежда.

Заранее большое спасибо за вашу помощь.

Джастин

Вы когда-нибудь находили решение для этого? Cristian Vrabie

Ваш Ответ

6   ответов
1

используя Google Calendar API (OAuth 2.0). Я тоже столкнулся с этой же ошибкой. Но теперь я исправил ошибку. Я пишу сценарий и решение для него.
URL-адрес получения события календаря для определенного календаря (API мобильного приложения):

https://www.googleapis.com/calendar/v3/calendars/en.indian%23holiday%40group.v.calendar.google.com/events?access_token=ya29.AHES6ZQyP3iDZM8PF-7ZqZE8oKmWAgUX55sPGPTjGbM5A

В этом URL мы должны добавить calendarId. Формат URL-адреса:

https://www.googleapis.com/calendar/v3/calendars/<calendarId>/events

Я не кодировал calendarId перед добавлением в URL. Я кодировал calendarId, а затем сделал запрос Http. Все прошло хорошо тогда.

final String accessToken=dataStore.getAccessToken();

    List<NameValuePair> params = new LinkedList<NameValuePair>();
    params.add(new BasicNameValuePair("access_token", accessToken));
    String paramString = URLEncodedUtils.format(params, "utf-8");

    final String url = String.format(AuthConstants.CALENDAR_EVENTS_URI,URLEncoder.encode(calendarId))+"?"+ paramString;

Теперь события календаря возвращаются в формате JSON.

1

вам нужно будет указать пользователя, которого вы пытаетесь выдать.

То, как вы используете ServiceAccount прямо сейчас, действительно только для доступа к данным, связанным с вашим приложением или самой учетной записью службы. Поскольку вы хотите получить доступ к данным Календаря Google, вы должны быть администратором домена Служб Google с правами доступа к любым данным пользователя вашего домена - дайте мне знать, если я не прав. Данные Календаря Google принадлежат пользователям, поэтому вам нужно указать, какого пользователя вы пытаетесь олицетворять.

Чтобы сделать это с помощью Java, кажется, вам нужно использоватьGoogleCredential.Builder # setServiceAccountUser (String)

Пожалуйста, попробуй:

GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId("[email protected]")
        .setServiceAccountScopes(CalendarScopes.CALENDAR)
        .setServiceAccountPrivateKeyFromP12File(new File("/path/to/privatekey.p12"))
        .setServiceAccountUser("[email protected]")
        .build();

Кроме того, после того, как вы создали ключ учетной записи службы в своем проекте API (из консоли API), вам нужно будет добавить этот проект в список авторизованных сторонних приложений в cPanel. Более подробную информацию об этом можно найтиВот, & Quot; Идентификатор клиента & quot; вам нужно использовать тот, который привязан к ключу учетной записи службы и выглядит как<APP_ID>-<OTHER_KEY>.apps.googleusercontent.com

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Justin Phillips
Error: User Rate Limit Exceeded Justin Phillips
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
0

так что я поиграл с этим и преодолел ошибку 401, но теперь у меня 403. Однако я подробно опишу написанный мной код, который по крайней мере отвечает на проблему 401.

Я не изменил ни одной настройки учетной записи службы или заново сгенерировал ни один из ключей и т. Д., Это все то же самое.

Что изменилось, так это часть кода, и я обновился доv3r20lv1.12.0-beta календаря API.

Код ниже, как описано выше в OP, остается тем же, т.е.

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("[email protected]")
        .setServiceAccountScopes(CalendarScopes.CALENDAR)
        .setServiceAccountPrivateKeyFromP12File(new File("D:/3cd8XXXXXXXXXXXXXXXXXXXXXXXXXXXXXd635e-privatekey.p12"))
        .build();

Код для получения дескриптора для Календаря изменился, но это было вызвано изменением API:

Calendar calendar = new Calendar(HTTP_TRANSPORT, JSON_FACTORY, credential);

На этом этапе я могу перебрать свой календарь и просмотреть события, выполнив следующий код (это печатает сводку событий):

Events events = calendar.events().list(CALENDAR_ID).execute();

for (Event event : events.getItems())
{
    System.out.println(event.getSummary());
}

Но, если я пытаюсь обновить событие, я получаю ошибку 403 Forbidden. Я создам отдельную тему для этого и свяжу две темы вместе.

Спасибо всем за помощь!

РЕДАКТИРОВАТЬ:Вот это новая тема.

5

кажется, что это немного странно с Google API. Я нахожу первый раз, когда запускаю свое приложение через какое-то время, а затем, по-видимому, с разнородными интервалами в несколько часов, я всегда получаю 401. Во втором или третьем раунде оно фактически входит в систему.

Поведение даже учитывается в примере кода API задач Google.Вот.

Обратите внимание на этот код:

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. Это может быть какая-то особая проблема безопасности, которую необходимо решить в коде.

0

включатьhttps://www.googleapis.com/auth/userinfo.profile

1

если вы не добавили пользователя API в панели администратора (в вашем случае панель «Документы», я полагаю), например, в Google Analytics вы должны добавить нового пользователя, где адрес электронной почты совпадает с тем, который вы получили от API (предоставленным Учетная запись службы Google API, после создания закрытого ключа). В аналитике это выглядит так:

example in google analytics

Я не могу видеть, где пользователи установлены в консоли API. Justin Phillips
Error: User Rate Limit Exceededlink
Error: User Rate Limit Exceeded Justin Phillips

Похожие вопросы