如何在Python开发的AWS Lambda中实现Google API身份认证
解决方案
方案1:改用Lambda允许读写的临时目录(适合快速测试)
AWS Lambda仅开放/tmp目录的读写权限,默认其他路径均为只读。你可以直接修改凭证存储路径到临时目录:
# 仅修改存储路径即可适配临时读写 store = file.Storage('/tmp/token.json') creds = store.get() if not creds or creds.invalid: # credentials.json可以提前打包到Lambda部署包中,也可以从环境变量/Secrets Manager读取后转字典传入 flow = client.flow_from_clientsecrets('credentials.json', SCOPES) creds = tools.run_flow(flow, store) calendar_service = build('calendar', 'v3', credentials=creds)
注意:该方案存在缺陷,Lambda冷启动时
/tmp目录会被清空,每次冷启动都需要重新完成OAuth授权流程,仅适合临时调试使用,不建议生产环境使用。
方案2:自定义凭证存储器,无需本地文件写入(生产环境推荐)
你可以自行实现oauth2client的Storage抽象类,将凭证内容存储到AWS Secrets Manager、AWS Parameter Store等托管存储服务中,完全绕过本地文件系统写入:
- 先在本地运行原始代码,生成有效的
token.json文件,将文件内的完整JSON内容存入AWS Secrets Manager,命名为google_calendar_token - 在Lambda代码中实现自定义Storage类,读写直接对接Secrets Manager:
import boto3 import json from oauth2client.client import Storage secrets_manager = boto3.client('secretsmanager') class CustomStorage(Storage): def __init__(self, secret_name): self.secret_name = secret_name def locked_get(self): resp = secrets_manager.get_secret_value(SecretId=self.secret_name) creds_json = resp['SecretString'] return json.loads(creds_json) def locked_put(self, credentials): creds_json = json.dumps(credentials.to_json()) secrets_manager.put_secret_value( SecretId=self.secret_name, SecretString=creds_json ) def locked_delete(self): pass # 替换原来的file.Storage即可 store = CustomStorage('google_calendar_token') creds = store.get() if not creds or creds.invalid: # 也可以把credentials.json的内容存到Secrets Manager,读取后转字典传入flow_from_client_config flow = client.flow_from_clientsecrets('credentials.json', SCOPES) creds = tools.run_flow(flow, store) calendar_service = build('calendar', 'v3', credentials=creds)
方案3:使用Google服务账号替代用户OAuth(无交互场景最优解)
如果你操作的是己方可控的Google日历,不需要终端用户授权,直接使用Google服务账号即可完全规避token刷新存储的问题:
- 在Google Cloud控制台创建服务账号,下载JSON格式的密钥文件,将密钥内容存入Secrets Manager
- 给服务账号的邮箱地址授予目标日历的编辑权限
- 使用服务账号凭证初始化服务,无需存储刷新token:
from google.oauth2 import service_account from googleapiclient.discovery import build SCOPES = ['https://www.googleapis.com/auth/calendar'] # 从Secrets Manager读取服务账号密钥 sa_secret = json.loads(secrets_manager.get_secret_value(SecretId='google_sa_key')['SecretString']) creds = service_account.Credentials.from_service_account_info(sa_secret, scopes=SCOPES) calendar_service = build('calendar', 'v3', credentials=creds)
内容的提问来源于stack exchange,提问作者KineticSquid
相关产品推荐
相关产品推荐

