【问题标题】:Authenticating Google API with a service account with Java API使用具有 Java API 的服务帐户对 Google API 进行身份验证
【发布时间】:2012-08-03 09:31:15
【问题描述】:

我正在尝试使用 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 访问”选项卡下创建了一个服务帐户。
  • 下载了我的私钥(从上面的代码中引用)。
  • 鉴于我的服务帐户用户“可以编辑”在“团队”标签下的访问权限。
  • 启用计费。

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

谢谢..

【问题讨论】:

    标签: java oauth-2.0 google-bigquery


    【解决方案1】:

    服务帐号授权方法适用于 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());
        }
      }
    }
    

    【讨论】:

    • 谢谢,迈克尔.. 令人尴尬的是,我的密钥没有被正确读取。我的代码使用密钥的绝对路径。
    • 密钥应该保存在哪里?
    • @AakashParasha 密钥必须保存在本地,脚本才能读取它,但要确保它的安全,就好像它是提供对整个云项目的访问权限的密码(本质上是这样)跨度>
    • @MichaelManoochehri 我现在把它作为我的资源文件夹。这是一个 Maven 项目。没事吧?还是有其他通常遵循的做法?
    • 为什么这不适用于 .json serviceAccount?我正在使用 GoogleCredential.fromStream(fileToServiceAccount)?
    【解决方案2】:

    使用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();
    

    【讨论】:

      猜你喜欢
      • 2019-08-25
      • 1970-01-01
      • 2013-09-23
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      • 1970-01-01
      • 2017-03-01
      • 2022-01-06
      相关资源
      最近更新 更多