BigQuery和OAuth2

时间:2012-05-09 21:49:05

标签: java google-api oauth-2.0 google-bigquery

我正在尝试使用Service Account方法访问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();

我从第二行看到来自Google API控制台的帐户ID,如下所示:

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

我错过了什么?

4 个答案:

答案 0 :(得分:5)

尤里卡!埃里克和迈克尔的代码都运作良好。

通过在客户端计算机上错误地设置时间,可以重现问题中发布的错误。幸运的是,可以通过正确设置客户端计算机上的时间来解决

注意:为了它的价值,我使用“Internet时间设置”对话框中的“立即更新”按钮在Windows 7框上同步时间。我认为这应该是非常白痴的...但我想我打败了系统。它修正了秒数,但机器关闭了一分钟。之后,BigQuery调用失败了。手动更改时间后,它成功了。

答案 1 :(得分:2)

我们在Java库中的错误处理代码需要稍微改进一下!

用于请求OAuth访问令牌的签名JWT似乎失败。你可以通过启用@MichaelManoochehri上面提到的日志来看到这一点。

我认为只有少数事情会导致这种失败:

  1. 签名无效(使用错误的密钥)
  2. 服务帐户的电子邮件地址无效(我认为已被排除)
  3. 用于生成签名blob的无效日期/时间戳(发布日期和到期日期)
  4. 无效范围(我认为已被排除)
  5. 您应该使用适当的时区检查服务器上的日期/时间是否正确设置 - 同步到NTP。您可以使用time.gov查看美国官方原子钟时间。

答案 2 :(得分:1)

编辑:我在下面给出的答案与使用Google App Engine服务帐户相关 - 请留待此处参考。

仔细检查您是否已将服务帐户地址作为所有者添加到项目的团队页面中。

我建议使用AppIdentityCredential类来处理服务帐户身份验证。这是一个演示此内容的小片段,我将在BigQuery API开发者页面上添加有关此内容的其他文档。

此外,请确保您使用的是最新版本的Google Java API客户端(截至今天,它的版本为“v2-rev5-1.5.0-beta”here)。

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

答案 3 :(得分:-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()); 
}