Вопрос по oauth-2.0, java, google-api, google-bigquery – BigQuery и OAuth2

3

Я пытаюсь получить доступ к Google BigQuery с помощьюСервисный аккаунт подход. Мой код выглядит следующим образом:

<code>private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();

private static final JsonFactory JSON_FACTORY = new JacksonFactory();

GoogleCredential credentials = new GoogleCredential.Builder()
            .setTransport(HTTP_TRANSPORT)
            .setJsonFactory(JSON_FACTORY)
            .setServiceAccountId("[email protected]")
            .setServiceAccountScopes(BigqueryScopes.BIGQUERY)
            .setServiceAccountPrivateKeyFromP12File(
                    new File("PATH-TO-privatekey.p12"))
            .build();
    Bigquery bigquery = Bigquery.builder(HTTP_TRANSPORT, JSON_FACTORY).setHttpRequestInitializer(credentials)
            .build();
    com.google.api.services.bigquery.Bigquery.Datasets.List datasetRequest = bigquery.datasets().list(
            "PROJECT_ID");

    DatasetList datasetList = datasetRequest.execute();
    if (datasetList.getDatasets() != null) {
        java.util.List<Datasets> datasets = datasetList.getDatasets();
        System.out.println("Available datasets\n----------------");
        for (Datasets dataset : datasets) {
            System.out.format("%s\n", dataset.getDatasetReference().getDatasetId());
        }
    }
</code>

Но это бросает следующее исключение:

<code>Exception in thread "main"  com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
  "code" : 401,
  "errors" : [ {
    "domain" : "global",
    "location" : "Authorization",
    "locationType" : "header",
    "message" : "Authorization required",
    "reason" : "required"
  } ],
  "message" : "Authorization 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.bigquery.Bigquery$Datasets$List.execute(Bigquery.java:979)
</code>

Исключение вызывается в этой строке:

<code>  DatasetList datasetList = datasetRequest.execute();
</code>

Я получаю идентификатор учетной записи из консоли API Google со второй строки в разделе, который выглядит следующим образом:

<code>    Client ID:  XXXXX.apps.googleusercontent.com
    Email address:  [email protected]
</code>

Что мне не хватает?

Ваш Ответ

4   ответа
1

EDIT: The answer I gave below is relevant to using Google App Engine Service Accounts - leaving here for reference.

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

Я рекомендую использовать класс AppIdentityCredential для обработки аутентификации учетной записи службы. Вот небольшой фрагмент, демонстрирующий это, и я добавлю дополнительную документацию по этому вопросу на странице разработчика API BigQuery.

Кроме того, убедитесь, что вы используете последнюю версию клиента Google Java API (на сегодняшний день это версия v2-rev5-1.5.0-beta).Вот).

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.http.json.JsonHttpRequest;
import com.google.api.client.http.json.JsonHttpRequestInitializer;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.BigqueryRequest;

@SuppressWarnings("serial")
public class Bigquery_service_accounts_demoServlet<TRANSPORT> extends HttpServlet {

// ENTER YOUR PROJECT ID HERE
private static final String PROJECT_ID = "";

private static final HttpTransport TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
private static final String BIGQUERY_SCOPE = "https://www.googleapis.com/auth/bigquery";


AppIdentityCredential credential = new AppIdentityCredential(BIGQUERY_SCOPE);
Bigquery bigquery = Bigquery.builder(TRANSPORT,JSON_FACTORY)

 .setHttpRequestInitializer(credential)
 .setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
   public void initialize(JsonHttpRequest request) {
     BigqueryRequest bigqueryRequest = (BigqueryRequest) request;
     bigqueryRequest.setPrettyPrint(true);
   }
 }).build();    

public void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws IOException {
  resp.setContentType("text/plain");
  resp.getWriter().println(bigquery.datasets()
    .list(PROJECT_ID)
    .execute().toString());
 }
}
Спасибо за быстрый ответ, но он не работает. Я использую последние двоичные файлы API BigQuery (которые вы указали); google-api-client является зависимым от него, и его версия 1.8.0-бета. Согласно этомуjavadoc.google-api-java-client.googlecode.com/hg/1.8.0-beta/com/… этот класс должен быть частью этого, но это не так. Я рассматриваю двоичные файлы и исходный код на Maven Central здесь:search.maven.org/…. ediaz
5

Ошибка, опубликованная в вопросе, может быть воспроизведена путем неправильной установки времени на клиентском компьютере. К счастью,it can be solved by setting the time on the client machine correctly.

Примечание. Для этого я синхронизировал время в окне Windows 7 с помощью функции "Обновить сейчас". кнопка в разделе «Настройки времени интернета» Диалог. Я подумал, что это должно быть довольно идиотски защищенным ... но я думаю, я побил систему. Он исправил секунды, но оставил машину выключенной ровно на одну минуту. После этого вызов BigQuery не удался. Это удалось после того, как я вручную изменил время.

2

!

Похоже, что подписанный JWT для запроса маркера доступа OAuth не выполняется. Это можно увидеть, включив журналы, которые @MichaelManoochehri упоминал выше.

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

Invalid signature (using the wrong key) Invalid e-mail address for the service account (I think that's been ruled out) Invalid date/time stamp used for generating the signed blob (an issue date, and an expiration date) Invalid scope (I think that's been ruled out)

Вам следует убедиться, что на вашем сервере правильно установлены дата и время с правильным часовым поясом - синхронизируйте d с NTP. Вы можете использовать time.gov, чтобы увидеть официальное время атомных часов в США.

-1

import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.Bigquery.Datasets;
import com.google.api.services.bigquery.model.DatasetList;

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;


public class BigQueryJavaServiceAccount {

  private static final String SCOPE = "https://www.googleapis.com/auth/bigquery";
  private static final HttpTransport TRANSPORT = new NetHttpTransport();
  private static final JsonFactory JSON_FACTORY = new JacksonFactory();

  public static void main(String[] args) throws IOException, GeneralSecurityException {
    GoogleCredential credential = new GoogleCredential.Builder().setTransport(TRANSPORT)
        .setJsonFactory(JSON_FACTORY)
        .setServiceAccountId("[email protected]")
        .setServiceAccountScopes(SCOPE)
        .setServiceAccountPrivateKeyFromP12File(new File("my_file.p12"))
        .build();

    Bigquery bigquery = Bigquery.builder(TRANSPORT, JSON_FACTORY)
        .setApplicationName("Google-BigQuery-App/1.0")
        .setHttpRequestInitializer(credential).build();

    Datasets.List datasetRequest = bigquery.datasets().list("publicdata");
    DatasetList datasetList = datasetRequest.execute();
    System.out.format("%s\n", datasetList.toPrettyString()); 
}
@ediaz: Клиентская библиотека Google Java API в настоящее время не передает определенные ошибки OAuth в шаге build () клиента. Вы можете разрешить вывод на консоль всех HTTP-запросов, добавив этот аргумент к аргументам своей виртуальной машины в конфигурации запуска Eclipse: -Djava.util.logging.config.file = / tmp / javalogging.properties ; файл должен содержать следующее: handlers = java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level = CONFIG com.google.api.client.http.level = CONFIG
Увидетьcode.google.com/p/google-api-j,ava-client/source/browse/… для получения дополнительной информации
Я попробовал это с теми же результатами, не только добавил: System.out.println (BigqueryScopes.BIGQUERY); и я получил это значение:googleapis.com/auth/bigquery таким образом, область видимости была правильной. ediaz

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