使用Java API的服务帐户验证Google API

时间:2012-08-06 11:58:52

标签: java oauth-2.0 google-bigquery

我正在尝试使用oauth API通过Java API对Google服务帐户进行身份验证。我希望用它来访问Google Bigquery。我从API请求中返回“无效授权”。

以下是代码,它是基本身份验证示例的副本(不适用于Bigquery ..而是另一个Google API):

  /** Global instance of the HTTP transport. */
  private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();

  /** Global instance of the JSON factory. */
  private static final JsonFactory JSON_FACTORY = new JacksonFactory();

  private static Bigquery bigquery;  

public ServiceAccountExample() {

      try {
          try {

            GoogleCredential credential = new  GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
                .setJsonFactory(JSON_FACTORY)
                .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
                .setServiceAccountScopes(BigqueryScopes.BIGQUERY)
                .setServiceAccountPrivateKeyFromP12File(new File("GoogleBigQuery-privatekey.p12"))
                //.setRefreshListeners(refreshListeners)
                //.setServiceAccountUser("email.com")
                .build();


            credential.refreshToken();

            bigquery = new Bigquery.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                        //.setApplicationName("GoogleBigQuery/1.0")
                        .build();

            listDatasets(bigquery, "publicdata");

            return;
          } catch (IOException e) {
            System.err.println(e.getMessage());
          }
        } catch (Throwable t) {
          t.printStackTrace();
        }

}

SERVICE_ACCOUNT_EMAIL是表格的电子邮件地址:XXXXXXX@developer.gserviceaccount.com

如果我删除了credential.refreshToken()行,那么在第一次调用Bigquery时,它会在listsDatasets中失败...否则它会在credential.refreshToken()上失败并出现相同的错误。

BigQuery不接受服务帐户身份验证吗?

我相信我已经通过API控制台正确完成了所有工作。我有:

  • 打开了对Big Query API的访问权限。
  • 在“API访问”标签下创建了一个服务帐户。
  • 下载了我的私钥(从上面的代码中引用)。
  • 鉴于我的服务帐户用户“可以编辑”访问权限位于“小组”标签下。
  • 启用结算。

我错过了什么吗?还有什么我需要做的吗?

谢谢..

2 个答案:

答案 0 :(得分:9)

服务帐户授权方法适用于BigQuery。您无需致电credential.refreshToken()。确保可以从您的应用程序中读取您的私钥文件。这是一个例子:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
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.services.bigquery.Bigquery;
import com.google.api.services.bigquery.BigqueryScopes;
import com.google.api.services.bigquery.Bigquery.Projects;
import com.google.api.services.bigquery.model.*;

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

public class BigQueryJavaServiceAccount {

  public static void main(String[] args) throws IOException, InterruptedException, GeneralSecurityException {

    final HttpTransport TRANSPORT = new NetHttpTransport();
    final JsonFactory JSON_FACTORY = new JacksonFactory();

    GoogleCredential credential = new  GoogleCredential.Builder()
      .setTransport(TRANSPORT)
      .setJsonFactory(JSON_FACTORY)
      .setServiceAccountId("SOMETHING@developer.gserviceaccount.com")
      .setServiceAccountScopes(BigqueryScopes.BIGQUERY)
      .setServiceAccountPrivateKeyFromP12File(new File("key.p12"))
      .build();

    Bigquery bigquery = Bigquery.builder(TRANSPORT, JSON_FACTORY)
      .setHttpRequestInitializer(credential)
      .build();

    Projects.List projectListRequest = bigquery.projects().list();
    ProjectList projectList = projectListRequest.execute();
    List<ProjectList.Projects> projects = projectList.getProjects();
    System.out.println("Available projects\n----------------\n");
    for (ProjectList.Projects project : projects) {
      System.out.format("%s\n", project.getProjectReference().getProjectId());
    }
  }
}

答案 1 :(得分:0)

使用Google Cloud BigQuery client libraries的服务帐户密钥进行身份验证  (Maven package)你可以use Application Default Credentials

首先将GOOGLE_APPLICATION_CREDENTIALS环境变量设置为服务帐户JSON密钥文件的完整路径。在您的代码中,使用默认实例创建BigQuery服务对象。

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryOptions;
...
BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

这是推荐的方式,因为它可以在多个环境中使用相同的代码,例如在Google Compute Engine上,服务帐户是内置的,而不是使用密钥文件。

或者,您可能希望construct a credentials object manually from a service account key file并使用它创建BigQuery服务对象。

import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryOptions;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

...

// TODO: update to your key path. 
File credentialsPath = new File("service_account.json");

GoogleCredentials credentials;
try (FileInputStream serviceAccountStream = new FileInputStream(credentialsPath)) {
  credentials = ServiceAccountCredentials.fromStream(serviceAccountStream);
}

// Instantiate a client.
BigQuery bigquery =
    BigQueryOptions.newBuilder()
        .setCredentials(credentials)
        .build()
        .getService();