导读:本期聚焦于不吃香菜创作的《Google Cloud API 认证中Service Account和ADC到底有什么区别怎么选》,敬请观看详情。直接把凭据写死在代码里为什么在Google Cloud环境会失效。应用默认凭据(ADC)是一套让客户端库自动定位凭据的规范,它按固定顺序查找环境变量或元数据服务,无需手工传入密钥文件。Service Account则是具体的身份实体,以JSON密钥或运行时绑定形式存在。理解二者关系能避免本地能跑线上报权限错误的尴尬。本文从查找链路、密钥管理和多环境适配三方面说明使用方式。

在对接Google Cloud各类API时,认证环节往往决定了程序能否正常调用服务。很多团队在本地用JSON密钥文件跑通了代码,部署到Compute Engine或Cloud Run后却遇到权限拒绝,根本原因在于没有分清Service Account这一身份实体与ADC这一凭据发现机制。Service Account代表一个非人类的服务身份,而ADC是一套由Google客户端库实现的自动凭据加载规则,两者属于不同层面但紧密配合。只有把身份配置和凭据查找路径都理顺,才能保证应用在开发机、CI流水线和云端运行时都能稳定鉴权。

Google Cloud API 认证中Service Account和ADC到底有什么区别怎么选

Service Account的本质与密钥管理

Service Account是Google Cloud项目中的一个账号对象,它不属于自然人,而是供应用或虚拟机使用的身份。每个Service Account拥有唯一的邮箱地址,例如 my-app@my-project.iam.gserviceaccount.com,并通过对IAM角色绑定获得具体资源的操作权限。在认证体系中,它解决的是“谁在调用API”的问题。我们可以为不同微服务创建互相独立的Service Account,遵循最小权限原则,降低密钥泄露后的影响范围。

使用Service Account最常见的方式是生成JSON密钥文件,里面包含 private_keyclient_email 等字段。程序读取该文件后,利用私钥对请求做JWT签名完成鉴权。下面的Python示例展示了如何显式使用密钥文件构造客户端:

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

# 明确指定Service Account密钥路径
creds = service_account.Credentials.from_service_account_file(
    'path/to/key.json',
    scopes=['https://www.googleapis.com/auth/cloud-platform']
)

client = storage.Client(credentials=creds, project='my-project')
buckets = list(client.list_buckets())
print(buckets)

这种显式加载方式逻辑清晰,适合本地开发和测试。但它的缺陷在于密钥文件需要随代码或环境分发,一旦提交到仓库或泄露到公网,攻击者就能长期冒用该身份。因此在生产环境中,更推荐让Google云基础设施直接把Service Account绑定到资源上,例如给Cloud Run服务指定一个运行身份,此时根本不需要JSON文件。

除了文件密钥,还可以通过IAM服务账号密钥轮换策略降低风险。Google建议设置最长有效期并定期禁用旧密钥。对于已经绑定到计算资源的Service Account,应完全避免导出密钥,而是依赖平台内部的元数据服务完成令牌签发,这就自然引出了ADC机制。

ADC的工作机制与查找顺序

应用默认凭据(Application Default Credentials,简称ADC)并不是一种账号,而是一套客户端库遵守的凭据解析约定。它的目标是让同一份代码无需修改,就能在不同环境下自动找到正确的Service Account凭据。Google官方客户端库在初始化无显式凭据的客户端时,会按优先级依次检查多个位置。

ADC的查找链路通常是:首先检查环境变量 GOOGLE_APPLICATION_CREDENTIALS 是否指向一个JSON密钥文件;若未设置,则在运行于Google Cloud环境(如Compute Engine、GKE)时访问元数据服务 http://metadata.google.internal 获取绑定到实例的访问令牌;若以上都失败,会尝试使用本地安装的gcloud用户凭据。下面这段Go代码演示了完全不传凭据的客户端创建方式:

package main

import (
    "context"
    "fmt"
    "log"

    "cloud.google.com/go/storage"
)

func main() {
    ctx := context.Background()
    // 不传入任何Credential,客户端自动走ADC流程
    client, err := storage.NewClient(ctx)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    attrs, err := client.Bucket("my-bucket").Attrs(ctx)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(attrs.Name)
}

从代码可见,开发者无需关心私钥存放位置,库内部已经封装了ADC逻辑。在本地若设置了 GOOGLE_APPLICATION_CREDENTIALS=./key.json,程序就会用该Service Account;在Cloud Run上不设置该变量,库会自动向元数据服务请求属于运行身份的令牌。这种抽象极大简化了多环境配置。

需要注意的是,ADC只是“找凭据”的规则,它最终拿到的依然是某个Service Account(或用户账号)的身份。如果元数据服务返回的账号没有相应IAM权限,API调用仍会失败。因此排查ADC相关错误时,应同时确认环境变量指向的文件和云端绑定的账号权限是否正确。

多环境适配与最佳实践

在真实项目中,我们通常要兼顾本地开发、GitHub Actions流水线和云端部署三类环境。合理搭配Service Account与ADC可以避免把密钥硬编码进代码库。本地开发机通过 gcloud auth application-default login 生成用户级ADC文件,或用环境变量指向测试用Service Account密钥;CI环境则使用仓库密文注入 GOOGLE_APPLICATION_CREDENTIALS;云端运行时彻底删除该变量,依靠平台绑定身份。

下面的bash脚本展示了CI中安全地使用ADC加载Service Account的方式:

# 从CI密文写出密钥文件
echo "$GCP_KEY_JSON" > /tmp/sa.json
export GOOGLE_APPLICATION_CREDENTIALS=/tmp/sa.json

# 运行测试,客户端库通过ADC自动读取上述变量
python test_cloud.py

这种分层策略既保证了本地调试便利,又避免了生产环境私钥落地。另外,当应用需要同时模拟多个身份调用不同项目时,才适合在代码里显式用 service_account.Credentials 指定具体密钥,否则一律优先ADC。监控方面,可以开启Cloud Audit Logs观察各Service Account的调用行为,发现异常令牌使用及时轮换。

总结来看,Service Account是身份载体,ADC是凭据路由。理解二者关系后,团队能建立统一的认证代码规范:默认无参构造客户端、用环境变量或托管身份提供凭据、仅在跨身份场景显式加载密钥。这样不仅减少配置错误,也显著提升了Google Cloud API调用的安全性和可维护性。

Service_AccountADCGoogle_Cloud_API修改时间:2026-08-17 16:12:31

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。