3

サービス アカウントアプローチを使用して Google BigQuery にアクセスしようとしています。私のコードは次のとおりです。

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("XXXXX@developer.gserviceaccount.com")
            .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());
        }
    }

ただし、次の例外がスローされます。

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)

例外は次の行で発生します。

  DatasetList datasetList = datasetRequest.execute();

次のようなセクションの 2 行目から、Google の API コンソールからアカウント ID を取得しています。

    Client ID:  XXXXX.apps.googleusercontent.com
    Email address:  XXXXX@developer.gserviceaccount.com

私は何が欠けていますか?

4

4 に答える 4

5

ユーレカ!Eric と Michael のコードはどちらもうまく機能します。

質問に投稿されたエラーは、クライアント マシンの時間を誤って設定することで再現できます。幸いなことに、クライアント マシンの時刻を正しく設定することで解決できます

注: 参考までに、[インターネット時刻設定] ダイアログの [今すぐ更新] ボタンを使用して、Windows 7 ボックスの時刻を同期しました。私はそれがかなりばかげているはずだと考えました...しかし、私はシステムを打ち負かしたと思います。秒は修正されましたが、マシンはちょうど 1 分オフのままでした。その後、BigQuery 呼び出しは失敗しました。手動で時間を変更したら成功しました。

于 2012-05-10T22:56:56.860 に答える
2

Java ライブラリのエラー処理コードを少し改善する必要があります。

OAuth アクセス トークンをリクエストするための署名付き JWT が失敗しているようです。これは、@MichaelManoochehri が前述したログを有効にすることで確認できます。

この失敗の原因と思われるものはいくつかあります。

  1. 無効な署名 (間違った鍵を使用)
  2. サービス アカウントの無効な電子メール アドレス (除外されていると思います)
  3. 署名付き BLOB の生成に使用された日付/時刻スタンプが無効です (発行日と有効期限)
  4. 無効なスコープ (除外されていると思います)

サーバーで日付/時刻が適切なタイムゾーンで正しく設定されていることを確認する必要があります-NTPに同期します。time.gov を使用して、米国の公式原子時計時刻を確認できます。

于 2012-05-10T22:58:28.940 に答える
1

編集: 以下の回答は、Google App Engine サービス アカウントの使用に関連しています。参考までにここに残します。

サービス アカウントのアドレスを所有者としてプロジェクトのチーム ページに追加したことを再確認してください。

サービス アカウントの認証を処理するには、AppIdentityCredential クラスを使用することをお勧めします。これを示す小さなスニペットを次に示します。これに関する追加のドキュメントを BigQuery API デベロッパー ページに追加します。

また、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());
 }
}
于 2012-05-09T22:16:35.107 に答える
-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("XXXXXXX@developer.gserviceaccount.com")
        .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()); 
}
于 2012-05-10T01:05:20.050 に答える