简体   繁体   English

如何在 Heroku 上使用 Google API 凭据 json?

[英]How to use Google API credentials json on Heroku?

I'm making an app using Google Calendar API, and planning to build it on Heroku.我正在使用 Google Calendar API 制作一个应用程序,并计划在 Heroku 上构建它。
I have a problem about authentication.我有一个关于身份验证的问题。 Usually I use credential json file for that, but this time I don't want to upload it on Heroku for security reason.通常我为此使用凭证 json 文件,但这次出于安全原因我不想将其上传到 Heroku。
How can I make authentiation on Heroku?如何在 Heroku 上进行身份验证?

For now, I put my json to an env variable, and use oauth2client 's from_json method.现在,我把我的 json 放到一个环境变量中,并使用oauth2clientfrom_json方法。

def get_credentials():
    credentials_json = os.environ['GOOGLE_APPLICATION_CREDENTIALS']
    credentials = GoogleCredentials.from_json(credentials_json)
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else: # Needed only for compatibility with Python 2.6
            credentials = tools.run(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials 

But this code isn't perfect.但是这段代码并不完美。 If the credentials is invalid, I want the code to write the new credentials to the env variable, not to a new file.如果凭据无效,我希望代码将新凭据写入 env 变量,而不是新文件。
Is there any better way?有没有更好的办法?

I spent an entire day to find the solution because it's tricky.我花了一整天的时间寻找解决方案,因为它很棘手。 No matter your language, the solution will be the same.无论您使用哪种语言,解决方案都是一样的。

1 - Declare your env variables from in Heroku dashboard like : 1 - 在 Heroku 仪表板中声明您的环境变量,例如:

The GOOGLE_CREDENTIALS variable is the content of service account credential JSON file as is. GOOGLE_CREDENTIALS 变量是服务帐户凭据 JSON 文件的内容。 The GOOGLE_APPLICATION_CREDENTIALS env variable in the string "google-credentials.json"字符串“google-credentials.json”中的 GOOGLE_APPLICATION_CREDENTIALS 环境变量

2 - Once variables are declared, add the builpack from command line : 2 - 声明变量后,从命令行添加 builpack:

$ heroku buildpacks:add https://github.com/elishaterada/heroku-google-application-credentials-buildpack

3 - Make a push. 3 - 推动。 Update a tiny thing and push.更新一个小东西并推送。

4 - The buildpack will automatically generate a google-credentials.json and fill it with the content of the google credentials content. 4 - buildpack 将自动生成一个 google-credentials.json 并用 google 凭据内容的内容填充它。

If you failed at something, it will not work.如果你在某件事上失败了,它就不会起作用。 Check the content of the google-credentials.json with the Heroku bash.使用 Heroku bash 检查 google-credentials.json 的内容。

The buildpack mentioned by Maxime Boué is not working anymore because of the Heroku updates(18+).由于 Heroku 更新(18+),Maxime Boué 提到的 buildpack 不再工作。 However, below is a similar buildpack which is working.但是,下面是一个类似的 buildpack 正在工作。 It is actually a fork from the previous one.它实际上是前一个的叉子。

If anyone is still looking for this, I've just managed to get this working for Google Cloud Storage by storing the JSON directly in an env variable (no extra buildpacks).如果有人还在寻找这个,我刚刚通过将 JSON 直接存储在一个 env 变量中(没有额外的 buildpacks)设法让它适用于谷歌云存储。

You'll need to place the json credentials data into your env vars and install google-auth您需要将 json 凭据数据放入您的环境变量并安装google-auth

Then, parse the json and pass google credentials to the storage client:然后,解析 json 并将 google 凭据传递给存储客户端:

from google.cloud import storage
from google.oauth2 import service_account

# the json credentials stored as env variable
json_str = os.environ.get('GOOGLE_APPLICATION_CREDENTIALS')
# project name
gcp_project = os.environ.get('GCP_PROJECT') 

# generate json - if there are errors here remove newlines in .env
json_data = json.loads(json_str)
# the private_key needs to replace \n parsed as string literal with escaped newlines
json_data['private_key'] = json_data['private_key'].replace('\\n', '\n')

# use service_account to generate credentials object
credentials = service_account.Credentials.from_service_account_info(
    json_data)

# pass credentials AND project name to new client object (did not work wihout project name)
storage_client = storage.Client(
    project=gcp_project, credentials=credentials)

Hope this helps!希望这可以帮助!

EDIT: Clarified that this was for Google Cloud Storage.编辑:澄清这是针对谷歌云存储的。 These classes will differ for other services, but from the looks of other docs the different Google Client classes should allow the passing of credentials objects.这些类对于其他服务会有所不同,但从其他文档的外观来看,不同的 Google Client 类应该允许传递凭据对象。

The recommended buildpack doesn't work anymore.推荐的 buildpack 不再起作用。 Here's a quick, direct way to do the same:这是一种快速、直接的方法:

  1. Set config variables:设置配置变量:
heroku config:set GOOGLE_APPLICATION_CREDENTIALS=gcp_key.json
heroku config:set GOOGLE_CREDENTIALS=<CONTENTS OF YOU GCP KEY>

The GOOGLE_CREDENTIALS is easier to set in the Heroku dashboard. GOOGLE_CREDENTIALS 更容易在 Heroku 仪表板中设置。

  1. Create a .profile file in your repo with a line to write the json file:在您的存储库中创建一个.profile文件,其中包含一行来写入 json 文件:
echo ${GOOGLE_CREDENTIALS} > /app/gcp_key.json

.profile is run every time the container starts. .profile每次容器启动时都会运行。

  1. Obviously, commit the changes to .profile and push to Heroku, which will trigger a rebuild and thus create that gcp_key.json file.显然,将更改提交到.profile并推送到 Heroku,这将触发重建,从而创建gcp_key.json文件。

A more official Heroku documentation in this topic: https://elements.heroku.com/buildpacks/buyersight/heroku-google-application-credentials-buildpack本主题中更官方Heroku 文档https ://elements.heroku.com/buildpacks/buyersight/heroku-google-application-credentials-buildpack

I also used buyersight 's buildpack and it was the only one, which worked for me我还使用了 buyightbuildpack ,它是唯一一个对我有用的

As state above, the official Heroku documentation works ( https://elements.heroku.com/buildpacks/buyersight/heroku-google-application-credentials-buildpack ).如上所述,Heroku官方文档有效( https://elements.heroku.com/buildpacks/buyersight/heroku-google-application-credentials-buildpack )。

For PHP Laravel users though, the config variable GOOGLE_APPLICATION_CREDENTIALS should be set to ../google-credentials.json .但是对于 PHP Laravel 用户,配置变量GOOGLE_APPLICATION_CREDENTIALS应该设置为../google-credentials.json Otherwise, PHP will not find the file.否则,PHP 将找不到该文件。

Screenshot from Heroku Heroku 的截图

In case you do not want to use buildpack如果您不想使用 buildpack

1 - Add env variables in Heroku via dashboard or CLI: 1 - 通过仪表板或 CLI 在 Heroku 中添加环境变量:

GOOGLE_CREDENTIALS variable is the content of the service account credential JSON file. GOOGLE_CREDENTIALS 变量是服务帐户凭据 JSON 文件的内容。 GOOGLE_APPLICATION_CREDENTIALS = google-credentials.json GOOGLE_APPLICATION_CREDENTIALS = google-credentials.json

在此处输入图像描述

2 - Create a file called .profile on the root of your project with the following content 2 - 在项目的根目录上创建一个名为.profile的文件,其中包含以下内容

 echo ${GOOGLE_CREDENTIALS} > /app/google-credentials.json

3 - Push your code 3 - 推送您的代码

4 - During startup, the container starts a bash shell that runs any code in $HOME/.profile before executing the dyno's command. 4 - 在启动期间,容器启动一个 bash shell,它在执行测功机命令之前运行 $HOME/.profile 中的任何代码。

Note: For Laravel projects GOOGLE_APPLICATION_CREDENTIALS = ../google-credentials.json注意:对于 Laravel 项目 GOOGLE_APPLICATION_CREDENTIALS = ../google-credentials.json

您可以使用Heroku 平台 API从您的应用程序中更新 Heroku 环境变量

It seems that those buildpacks where you can upload the credentials.json file are not working as expected.您可以上传 credentials.json 文件的那些构建包似乎没有按预期工作。 I finally managed with Lepinsk's buildpack ( https://github.com/lepinsk/heroku-google-cloud-buildpack.git ), which requires all keys and values to be set as config vars in Heroku.我终于使用 Lepinsk 的 buildpack ( https://github.com/lepinsk/heroku-google-cloud-buildpack.git ) 进行了管理,这需要在 Heroku 中将所有键和值设置为配置变量。 It does do the job though, so lots of thanks for that!不过它确实可以完成这项工作,非常感谢!

I have done this like below:我已经这样做了,如下所示:

  • Created two env variable创建了两个环境变量
    1. CREDENTIALS - base64 encoded value of google api credential CREDENTIALS - google api 凭据的 base64 编码值
    2. CONFIG_FILE_PATH - /app/.gcp/key.json (this file we will create it at run time. in heroku preinstall phase as below) CONFIG_FILE_PATH - /app/.gcp/key.json(这个文件我们将在运行时创建。在heroku预安装阶段如下)

Create a preinstall script.创建预安装脚本。

"heroku-prebuild": "bash preinstall.sh",

And in preinstall.sh file, decode CREDENTIALS and create a config file and update it there.在 preinstall.sh 文件中,解码 CREDENTIALS 并创建一个配置文件并在那里更新它。

if [ "$CREDENTIALS" != "" ]; then


echo "Detected credentials. Adding credentials" >&1
  echo "" >&1

  # Ensure we have an gcp folder
  if [ ! -d ./.gcp ]; then
    mkdir -p ./.gcp
    chmod 700 ./.gcp
  fi

  # Load the private key into a file.
  echo $GCP_CREDENTIALS | base64 --decode > ./.gcp/key.json

  # Change the permissions on the file to
  # be read-only for this user.
  chmod 400 ./.gcp/key.json
fi

If you're still having an issue running the app after following the buildpack instructions already mentioned in this article, try setting your Heroku environment variable GOOGLE_APPLICATION_CREDENTIALS to the full path instead.如果按照本文中已经提到的 buildpack 说明运行应用程序后仍然遇到问题,请尝试将 Heroku 环境变量GOOGLE_APPLICATION_CREDENTIALS设置为完整路径。

GOOGLE_APPLICATION_CREDENTIALS = /app/google-credentials.json GOOGLE_APPLICATION_CREDENTIALS = /app/google-credentials.json

This worked for me.这对我有用。

Previously, I could see that the google-credentials file was already generated by the buildpack (or .profile) but the Heroku app wasn't finding it, and giving errors as:以前,我可以看到 google-credentials 文件已经由 buildpack(或 .profile)生成,但 Heroku 应用程序没有找到它,并给出如下错误:

Error: Cannot find module './google-credentials.json'
Require stack:
- /app/server/src/config/firebase.js
- /app/server/src/middlewares/authFirebase.js
- /app/server/src/routes/v1/auth.route.js
- /app/server/src/routes/v1/index.js
- /app/server/src/app.js
- /app/server/src/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:902:15)
    at Module.Hook._require.Module.require (/app/server/node_modules/require-in-the-middle/index.js:61:29)
    at require (internal/modules/cjs/helpers.js:93:18)
    at Object.<anonymous> (/app/server/src/config/firebase.js:3:24)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)

I just have to add this tip, be careful on making GOOGLE_APPLICATION_CREDENTIALS variable in heroku dashborad, it caused me a day, if you have path like that for the credential file: server\credential.json , that will not work because using the backslash , so use slash instead / :我只需要添加这个提示,在 heroku dashborad 中制作 GOOGLE_APPLICATION_CREDENTIALS 变量时要小心,如果你有这样的凭证文件路径: server\credential.json ,那将不起作用,因为使用反斜杠,所以使用斜线代替 /
this will work as path (without "):这将作为路径(不带“):
server / credential.json服务器/凭证.json

The simplest way I've found is to我发现的最简单的方法是

  1. Save the credentials as a string in a heroku ENV variable将凭据保存为 Heroku ENV 变量中的字符串
  2. In you app, load them into a Ruby Tempfile在您的应用程序中,将它们加载到 Ruby 临时文件中
  3. Then have the GoogleDrive::Session.from_service_account_key load them from that temp file然后让GoogleDrive::Session.from_service_account_key从该临时文件加载它们
require "tempfile"

...

google_credentials_tempfile = Tempfile.new("credentials.json")
google_credentials_tempfile.write(ENV["GOOGLE_CREDENTIALS_JSON"])
google_credentials_tempfile.rewind

session = GoogleDrive::Session.from_service_account_key(google_credentials_tempfile)

I have this in a heroku app and it works flawlessly.我在heroku应用程序中有这个,它完美无缺。

I know this is old, but there is another alternative - ie to "split" the json file and store each important field as its own environment variable.我知道这是旧的,但还有另一种选择 - 即“拆分” json 文件并将每个重要字段存储为它自己的环境变量。

Something like:就像是:

PRIVATE_KEY_ID=qsd
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
CLIENT_EMAIL=blabla@lalala.iam.gserviceaccount.com
CLIENT_ID=7777
CLIENT_X509_CERT_URL=https://www.googleapis.com/robot/v1/metadata/x509/whatever.iam.gserviceaccount.com

This can be in a .env file locally, and put on heroku using the UI or heroku config:set commands这可以在本地的 .env 文件中,并使用 UI 或 heroku config:set 命令放在 heroku

Then in the python file, you can initialize the ServiceAccount using a dict instead of a JSON然后在 python 文件中,您可以使用 dict 而不是 JSON 来初始化 ServiceAccount

CREDENTIALS = {
    "type": "service_account",
    "project_id": "iospress",
    "private_key_id": os.environ["PRIVATE_KEY_ID"],
    "private_key": os.environ["PRIVATE_KEY"],
    "client_email": os.environ["CLIENT_EMAIL"],
    "client_id": os.environ["CLIENT_ID"],
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": os.environ["CLIENT_X509_CERT_URL"]
}

credentials = ServiceAccountCredentials.from_json_keyfile_dict(CREDENTIALS, SCOPES)

It's a bit more verbose than some of the options presented here, but it works without any buildback or other它比这里介绍的一些选项更冗长,但它可以在没有任何构建或其他的情况下工作

you can change the scripts like this in your packge.json, set the file json path in GOOGLE_APPLICATION_CREDENTIALS您可以在 packge.json 中更改这样的脚本,在 GOOGLE_APPLICATION_CREDENTIALS 中设置文件 json 路径

"scripts": {
    "start": "GOOGLE_APPLICATION_CREDENTIALS=./yourfile.json node app.js"
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何通过Google API将JSON字符串用作凭证而不是Python的文件路径 - How to use JSON string as credentials instead of filepath for Python with Google API 如何使用从谷歌获得的凭据与谷歌 API - How to use credentials obtained from google with google API 如何设置Google凭据以从Heroku上的Python应用程序调用Google API - How to set Google Credentials to call Google API from Python app on Heroku 如何在 Pyinstaller 中包含 Google API JSON 凭证文件? - How to include Google API JSON credentials file in Pyinstaller? 如何使用对象中的Google Calendar API凭据 - How to use Google Calendar API credentials from objects 如何在Python中将OAuth2Credentials与Google API gdata客户端一起使用? - How to use OAuth2Credentials with Google API gdata client in python? 我应该如何在我的系统上存储 Google Drive API credentials.json? - How should I store the Google Drive API credentials.json on my system? 在 Python 项目中设置 GOOGLE_APPLICATION_CREDENTIALS 以使用谷歌 API - Set GOOGLE_APPLICATION_CREDENTIALS in Python project to use Google API 如何使用 API 密钥或 OAuth 客户端 ID 作为凭据将文件上传到 Google 可以平台? - How to use API Key or OAuth client ID as Credentials to upload file to Google Could Platform? 如何在Python 37中使用带有标准Google App Engine凭据的Drive API? - How to use Drive API with credentials of a standard Google App Engine in Python 37?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM