GCS:对象身份、权限与版本机制
Bucket、ADC 与对象身份
范围、版本与学习前置
本系列的 GCS 指 Google Cloud Storage,面向普通对象存储 Bucket 与原生 Python 客户端 google-cloud-storage>=3.0,<4,使用 Python 3.10+。不是 Firebase 权限规则教程,也不使用 S3 互操作接口。2026-10-17 核对中英文官方文档和 Python Blob 合同;依赖只声明版本族,没有安装或锁定传递依赖,不声称最新或已经实测。所有示例未执行,本轮没有账号登录、API 调用、产品服务或模拟器。
读者应理解 HTTP、Python 异常和环境变量;按本篇、机制、CLI、维护、复习阅读。不具备云环境也能以请求序列完成练习。
对象名称与身份
GCS 对象名称是 Bucket 内的字符串;exports/a.json 不意味着本地目录。普通平面命名空间中的前缀列表和真正的层次命名空间能力要分开理解,本系列不使用后者。应用引用应保存 bucket、name 与 generation,而非一个可变的 gs://bucket/name。同名内容替换会产生新的 generation;仅名称无法唯一指定已经发布的字节序列。对象元数据定义了这些属性。
location 是 Bucket 的放置配置,project 关联资源管理和计费;把不同 project 传给客户端不等于自动获得目标桶权限。读者还要区分资源项目、配额项目和 Requester Pays 账单项目,本示例不配置 Requester Pays。列表的 prefix 仅过滤结果,不构成身份授权,也不是多对象事务快照。
ADC 凭据链与最小权限
GCS ADC 凭据链通常按 GOOGLE_APPLICATION_CREDENTIALS 指定配置、本地 ADC 文件、运行环境附加身份的顺序寻找凭据。普通 gcloud auth login 与 application-default 登录不是同一个凭据存储。跨云或外部运行环境优先 Workload Identity Federation;配置文件可以描述联合身份,并不必然包含服务账号私钥。本文不执行任何登录命令。官方认证说明给出了客户端认证入口。
GCS 最小权限要按动作核对 storage.objects.list、storage.objects.get、storage.objects.create 和 storage.objects.delete;只创建新名可以只给 create,覆盖已有对象通常还涉及 delete。示例的 list/get/put/delete 需要组合权限,不能因此把整个项目 Storage Admin 授给应用。Bucket IAM、统一桶级访问与条件授权的选择要独立评估:不能假定任意 resource.name 前缀条件都能把 list 的结果自动裁剪到前缀。SDK 参数校验只保护误操作,服务端授权才是安全边界。
CLI 阅读入口与成本
GCS CLI 指本仓库 examples/gcs/object_cli.py;读者可从 argparse 看出 list、put、get、sign、delete 五种操作。它不创建 Bucket,不改 IAM。put 限制 1 MiB 并生成随机名,delete 强制 generation;list 则自动翻页,成本可能随对象数量增长。静态阅读不产生产品费用,自行运行会产生请求、存储、下载或跨位置流量,以及保留历史版本、软删除数据的费用。
练习:为什么附加身份能 GET 却不一定能生成签名 URL?答案是 OAuth 访问令牌可授权 API 读取,但 V4 URL 需要签名能力;普通用户 ADC 不一定提供私钥或远程签名接口。这一差别在签名机制展开,不能通过下载一份长期私钥来绕过权限设计。
官方来源
依据:中文前提条件、认证、Python Blob 参考。这些来源适用 GCS 原生合同,后文不把 AWS 的 VersionId、删除标记或 IAM 动作名套过来。
generation、前提条件与可恢复上传
generation 与 metageneration
前置是 对象身份。GCS generation 标识一个内容版本,metageneration 标识该 generation 的元数据修订。替换字节会产生新 generation,修改自定义元数据则更新 metageneration。不要把 metageneration 单独作为跨内容版本的唯一身份,也不要将两者看作时间戳。若业务必须“只修改我刚读到的那份对象的元数据”,应同时绑定 generation 与 metageneration。官方元数据合同明确两者用途。
例如 A 读取 generation=10、metageneration=1,B 替换内容成 generation=11、metageneration=1;A 只比对 metageneration=1 不能表达“仍是内容10”。这个例子是模型推演,数字仅为示意,不意味着实际号码顺序连续。Blob 实例上缓存的属性也不是服务端实时值,reload 才会重新读取。
前提条件与并发重试
GCS 前提条件 if_generation_match=0 表示只有不存在 live 对象时才创建;非零值表示当前目标必须匹配指定 generation。冲突返回 412 Precondition Failed,应用应重新读取状态并判断业务意图,不能删除条件再盲重试。元数据更新使用 if_metageneration_match,复制或 rewrite 还需分别区分源条件和目标条件。官方请求前提条件说明了 0 的特殊语义。
GCS 删除重试若绑定同一 generation,就不会误删之后新建的对象;如果只按名称重试,旧请求晚到可能删除新内容。条件重试策略允许在可证明幂等的条件下重试,不能将其理解成所有写请求都可重放。CLI 上传使用随机名加 generation=0,删除强制精确 generation;它没有业务幂等键,重复执行 put 仍产生另一个对象。
Object Versioning 与软删除
GCS 版本保留使用 noncurrent generation 的概念,而不是 S3 删除标记。Object Versioning 开启时,替换 live 内容保留旧 generation;普通删除 live 对象可使它变为 noncurrent。soft delete 是另一个桶级保护机制,删除后的对象可能进入有保留期限的软删除状态;其实际效果取决于两个功能的组合和桶配置。不要把“版本保留”“软删除”“保留策略”混为一项开关。恢复需要明确 generation 与状态,不能靠普通 list 缺失推断永久删除。官方生命周期说明区分清理动作与软删除效果。
CRC32C 与可恢复上传
GCS CRC32C 是常用传输完整性校验,和 OSS CRC64、S3 CRC64NVME 并非同一种算法。示例安装声明包含 google-crc32c 并显式要求 checksum='crc32c';业务 SHA-256 仍应单独记录。ETag 不应替代全文摘要;范围下载、转换传输或未读完整流时也不能声称已验证全文。Python Blob 参考列出 checksum 与前提条件参数。
GCS 可恢复上传先获得 session URI,随后按协议提交字节和查询已接收范围;不能照搬 S3 的 uploadId、partNumber、CompleteMultipartUpload 模型。session URI 本身有上传能力,泄漏到日志也会泄漏授权。重新开始一个 session 可能重复传输,恢复时应核对服务端已接收位置和本地文件是否改变。CLI 小文件路径不演示断点恢复,官方 resumable uploads是扩展阅读。
V4 URL 的签名能力
GCS V4 签名 URL 是受方法、路径、有效期与签名字段约束的持有者能力,通常针对 XML API 端点。能用 ADC 调用 JSON API 不代表该凭据能直接调用 generate_signed_url。服务账号私钥或受控的远程签名方案必须另行配置,远程 signBlob 所需 IAM 与对象读取权限也是两项授权。示例只调用客户端签名方法,缺少签名能力时失败退出,不尝试自动创建密钥或授予角色。官方签名 URL 文档说明其认证边界。
练习:签发五分钟 URL 后,接受者可否把 GET 改成 DELETE?答案:不能,方法参与签名;但同一 GET URL 在过期前可能被多次使用,因此它也不是“一次性下载券”。
继续阅读
- 应用实践
- 知识专题