使用带有 Java API 的服务帐户对 Google API 进行身份验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11827817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 06:31:53  来源:igfitidea点击:

Authenticating Google API with a service account with Java API

javaoauth-2.0google-bigquery

提问by Sprooose

I am attempting to use oauth API to authenticate a google service account through the Java API. I am hoping to use it to access Google Bigquery. I get an "invalid grant" returned from my API requests.

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

Here is the code, which is a copy of a basic authentication example (which wasn't for Bigquery.. but another Google 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 HymansonFactory();

  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 is the email address of the form: [email protected]

SERVICE_ACCOUNT_EMAIL 是表单的电子邮件地址:[email protected]

If I remove the credential.refreshToken() line, it fails in the listsDatasets on the first call to Bigquery... Otherwise it fails on credential.refreshToken().. with the same error.

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

Does BigQuery not accept Service Account authentication?

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

I believe I have done everything correctly through the API Console. I have:

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

  • Turned access to the Big Query API on.
  • Created a service account under the "API Access" tab.
  • Downloaded my private key (which is referenced from the code above).
  • Given my service account user "can edit" access under the "Teams" tab.
  • Enabled Billing.
  • 开启了对 Big Query API 的访问。
  • 在“API 访问”选项卡下创建了一个服务帐户。
  • 下载了我的私钥(从上面的代码中引用)。
  • 鉴于我的服务帐户用户在“团队”选项卡下“可以编辑”访问权限。
  • 启用计费。

Have I missed anything? Is there anything else I need to do?

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

Thanks..

谢谢..

回答by Michael Manoochehri

The service account authorization method works just fine with BigQuery. You don't need to call credential.refreshToken(). Make sure that your private key file can be read from your application. Here is an example:

服务帐户授权方法适用于 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.Hymanson.HymansonFactory;

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

    GoogleCredential credential = new  GoogleCredential.Builder()
      .setTransport(TRANSPORT)
      .setJsonFactory(JSON_FACTORY)
      .setServiceAccountId("[email protected]")
      .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());
    }
  }
}

回答by Tim Swast

To authenticate with a service account key with the Google Cloud BigQuery client libraries(Maven package) you can use Application Default Credentials.

要使用Google Cloud BigQuery 客户端库Maven 包)的服务帐户密钥进行身份验证,您可以使用应用程序默认凭据

First set the GOOGLE_APPLICATION_CREDENTIALSenvironment variable to the full path to your service account JSON key file. In your code, create the BigQuery service object using the default instance.

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

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

This is the recommended way, as it makes it possible to use the same code in multiple environments, such as on Google Compute Engine, where the service account is built-in rather than using a key file.

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

Alternatively, you may wish to construct a credentials object manually from a service account key fileand use that create the BigQuery service object.

或者,您可能希望从服务帐户密钥文件手动构建凭据对象,并使用它创建 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();