使用 GAE 服务帐户 JSON 密钥

Posted

技术标签:

【中文标题】使用 GAE 服务帐户 JSON 密钥【英文标题】:Use GAE Service Account JSON key 【发布时间】:2014-09-07 00:12:42 【问题描述】:

我在 GAE 中有一个应用程序,我正在使用服务帐户来调用一些谷歌服务。当我在仪表板中创建服务帐户时,向我提供了一个 JSON 密钥。 json的内容是这样的:


  "private_key_id": "bar-foo",
  "private_key": "-----BEGIN PRIVATE KEY-----foo-bar\n-----END PRIVATE KEY-----\n",
  "client_email": "foo-bar@developer.gserviceaccount.com",
  "client_id": "bar-foo.apps.googleusercontent.com",
  "type": "service_account"

如何在我的 java 代码中使用此 private_key 来生成 GoogleCredential 对象?

我可以使用setServiceAccountPrivateKeyFromP12File 方法做到这一点,但为此我需要创建一个 p12 文件并将其存储在某处。使用 json 私钥,我可以在我的属性文件中配置它。

我在GoogleCredential.Builder 中找到了一个setServiceAccountPrivate 方法,它接收一个PrivateKey 对象作为参数,但我不知道如何从json 中的值生成这个对象。我发现的所有示例都使用 p12 文件。

【问题讨论】:

【参考方案1】:

由于这个问题仍在获得意见并且没有公认的答案,这里有一个如何使用 JSON 密钥和谷歌 API 客户端库的示例,略微改编自官方文档部分“Using OAuth 2.0 with the Google API Client Library for Java”:

HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
...
// Build service account credential.

GoogleCredential credential = GoogleCredential.fromStream(MyClass.class.getResourceAsStream("/MyProject-1234.json"))
    .createScoped(Collections.singleton(PlusScopes.PLUS_ME));
  // Set up global Plus instance.
  plus = new Plus.Builder(httpTransport, jsonFactory, credential)
      .setApplicationName(APPLICATION_NAME).build();

您可以放置​​您的密钥文件,例如。 'MyProject-1234.json' 到 /src/main/resources 和上面的 'MyClass' 是指包含您的方法的父类的名称。

【讨论】:

你把“MyProject-1234.json”放在你的项目结构中的什么位置? 我意识到该示例仅包含一个通用文件读取示例,因此我编辑了我的答案以包含一种适用于 App Engine 的方式。这实际上适用于任何 servlet 应用程序,并且还有其他方法可以做到这一点,例如。将其放在“WEB-INF”下并使用 getServletContext().getResourceAsStream("/WEB-INF/MyProject-1234.json")。 将私钥文件放在WEB-INF下不会造成安全问题吗? WEB-INF 不是公共文档树的一部分,不应该提供给客户,但是对于偏执狂(包括我自己),我建议坚持使用 /src/main/resources。我提到它是为了完整性,因为它是在 GAE 中读取文件资源的支持方式。 fromStream 方法不可见【参考方案2】:

您应该在创建项目时使用 GAE 代表您创建的内置服务帐户。您可以在此处查看如何使用它的示例:https://developers.google.com/bigquery/authorization#service-accounts-appengine

您可以从这里的其他问题中找到更多关于服务帐户的信息:https://***.com/a/24478017/700188(它适用于 python,但应该有相应的 java 文章)

编辑

这是一篇关于使用内置服务帐户身份与 Google 的 API 通信的 Google AppEngine 文档:

https://developers.google.com/appengine/docs/java/appidentity/#Java_Asserting_identity_to_Google_APIs

没有必要为 GAE 使用单独的服务帐户,因为已经为您提供了一个。

编辑 2

不确定 JSON 文件中的私钥是否与 p12 文件中的私钥相同,但如果是,您可以尝试类似(抱歉,我的 Java 可能有点生锈):

import com.google.api.client.util.SecurityUtils;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.PrivateKey;
// Read the JSON Private key as a byte[] array into bytes
PrivateKey serviceAccountPrivateKey = SecurityUtils.getRsaKeyFactory().generatePrivate(new PKCS8EncodedKeySpec(bytes));

【讨论】:

不确定我们在这里讨论的是否相同。 您是否尝试从您的 GAE 应用访问通过 Cloud Console 启用的 Google API? 是的,我正在使用通过控制台启用的 Google API。 那么我认为您应该使用您在 GAE 应用中获得的服务帐户,这样您就不必担心 JSON 和 P12 文件之类的事情。 您可以通过该项目的 Cloud Console 中的“权限”菜单将您的 GAE 应用的服务帐户添加到该项目。您的服务帐户的格式应为your_app_id@appspot.gserviceaccount.com

以上是关于使用 GAE 服务帐户 JSON 密钥的主要内容,如果未能解决你的问题,请参考以下文章

无法使用服务帐户授权连接到自己的 GAE 端点 API

IRS 电子服务帐户的 JSON 网络密钥 (JWK)

如何使用服务帐户密钥通过 ADF 连接到 Google 云存储

使用 Json 文件进行 Google 服务帐户身份验证

使用 Google Cloud 服务帐户是 VSTS 构建

简单的 GAE Java JSON REST 服务器