GCP服务账号对应的Access Token有效期是否与服务账号一致?
Access Token 有效期说明
通过gcloud auth application-default print-access-token生成的访问令牌不会和服务账号生命周期绑定,默认固定有效期为1小时(3600秒),过期后调用PubSub接口会直接返回401 Unauthorized错误。你计划在Jenkins部署阶段生成一次令牌就写入应用配置长期使用的方案完全不可行,服务上线后最多1小时就会持续出现事件发布失败的问题。
GCP不支持将服务账号访问令牌设置为永久有效,最长有效期硬限制为1小时,所有生产可用方案都必须实现令牌定期刷新逻辑。
无重型GCP依赖的可行刷新方案
以下方案都不需要引入Spring Cloud GCP、PubSubTemplate这类会引发依赖冲突的重型组件,仅靠你当前已经在使用的RestTemplate即可实现:
- 方案1:调用GCP元数据服务自动拉取(最推荐,适用于GCP环境部署)
如果应用部署在GCP生态的运行环境中(GCE、GKE、Cloud Run、Cloud Functions等),不需要提前生成令牌,也不需要配置服务账号密钥,直接在代码中定时调用GCP实例内置的元数据服务接口即可获取有效令牌。
接口调用方式非常简单,发送GET请求时带上固定请求头Metadata-Flavor: Google,无需额外鉴权信息:
接口返回的JSON结构中包含GET http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/tokenaccess_token(令牌值)和expires_in(剩余有效秒数)字段,你只需要在本地缓存令牌,在过期前5分钟左右重新调用接口拉取新令牌即可,整个逻辑不需要引入任何第三方依赖,完全没有依赖冲突风险。 - 方案2:基于服务账号密钥轻量生成令牌(适用于非GCP环境部署)
如果应用部署在自建IDC、其他云厂商服务器等非GCP环境,无法访问元数据服务,可以将服务账号JSON密钥文件存放到服务器的安全路径下,自行实现极简的OAuth2令牌生成逻辑,不需要引入Google官方SDK:- 读取密钥文件中的
client_email和private_key字段 - 按照OAuth2.0 JWT规范生成签名断言,设置断言有效期1小时,受众值为
https://oauth2.googleapis.com/token - 用RestTemplate向Google OAuth2端点提交断言换取access_token,本地缓存令牌并在过期前重新生成即可
这个实现仅需要一个轻量JWT工具库(多数老版本Spring项目本身已经内置这类依赖),不会引入GCP生态的重型依赖,冲突风险极低。
- 读取密钥文件中的
- 方案3:旁路Sidecar代理刷新(零业务代码改造)
如果不想在业务代码中实现令牌刷新逻辑,可以在应用同主机/同Pod下部署一个极轻量的令牌刷新代理,由代理负责定时刷新有效令牌:要么定时将最新令牌写入本地配置文件供应用读取,要么直接反向代理PubSub的接口请求,自动补全Authorization请求头。业务代码不需要做任何调整,连令牌拼接的逻辑都不用修改。
注意:不要尝试通过任何配置拉长访问令牌的有效期,GCP对服务账号访问令牌的最长有效期硬限制为1小时,没有放开永久令牌的配置入口。
内容的提问来源于stack exchange,提问作者Marina
相关产品推荐
相关产品推荐

