V2 签名流程

本页面提供了使用 V2 签名流程(一种对存储桶和对象执行查询字符串身份验证的机制)时的签名网址概览。借助签名网址,您可以向拥有该网址的任何人提供有时限的读取或写入权限(无论他们是否拥有用户账号)。

需要签名的字符串的各个组成部分

使用程序创建签名网址时,程序会构造一个需要签名的字符串。该字符串应在您的程序中定义为如下形式:

StringToSign = HTTP_Verb + "\n" +
               Content_MD5 + "\n" +
               Content_Type + "\n" +
               Expires + "\n" +
               Canonicalized_Extension_Headers +
               Canonicalized_Resource

组成此结构的各个组成部分如下表所述:

字符串的组成部分 示例 说明
HTTP_Verb GET 必需。要与签名网址结合使用的 HTTP 动词

注意:除非如上所述,否则签名网址字符串不支持 HTTP 谓词 POST。您可以使用 POST 来定义签名政策文档(指定了可以上传到存储桶的对象的特征)。如需了解详情,请参阅 POST 对象文档。

Content_MD5 rmYdCNHKFXam78uCt7xQLw== 可选。采用 Base64 编码的 MD5 digest 值。如果在字符串中提供此内容,客户端(通常是浏览器)必须在请求中提供此 HTTP 标头(具有相同的值)。
Content_Type text/plain 按需。如果提供 content-type,则客户端(浏览器)必须提供此 HTTP 标头(设置为相同的值)。
Expires 1388534400 必需。这是代表签名到期时间的时间戳(表示为与 UNIX 计时原点 - 1970 年 1 月 1 日 UTC 时间 00:00:00 - 之间相隔的秒数)。服务器会拒绝此时间戳之后收到的任何请求,以及用于生成签名网址的密钥轮替之后收到的任何请求。为了确保安全性以及与 V4 签名流程的兼容性,您应将 Expires 设置为与未来最多 1 周(604800 秒)对应的时间。
Canonicalized_Extension_Headers x-goog-acl:public-read\nx-goog-meta-foo:bar,baz\n 按需。服务器会检查并确保客户端在使用签名网址的请求中提供匹配的值。要了解如何为签名创建规范标头,请参阅规范扩展标头
Canonicalized_Resource /bucket/objectname 必需。在网址中寻址的资源。如需了解详情,请参阅规范资源

使用 App Engine App Identity 服务对字符串进行签名

使用程序创建签名网址时,您可以在程序中对字符串签名,也可以使用 App Engine Identity 服务(该服务使用 App Engine 的服务账号凭据)从 App Engine 应用中进行签名。例如,借助 Python App Identity API,您可以执行以下操作:

  • 使用 google.appengine.api.app_identity.sign_blob() 从您构造的字符串中对字节签名,然后在组合签名网址时提供所需的 Signature

  • 使用 google.appengine.api.app_identity.get_service_account_name() 检索服务账号名称(这是您在组合签名网址时需要用到的 GoogleAccessId)。

有关其他语言的支持,请参阅 Java 版 App Identity API 概览PHP 版 App Identity API 概览App Identity Go 函数

App Identity 服务在签署 blob 时会轮替私钥。从 App Identity 服务生成的签名网址至少可以使用一小时,建议将其用于向用户授予资源的短期访问权限。

规范扩展标头

使用程序创建签名网址时,您会构造消息的“规范扩展标头”部分,为了执行此操作,您需要连接以 x-goog- 开头的所有扩展(自定义)标头。但是,您无法执行简单连接。在创建标头时,请牢记以下算法:

  1. 将所有自定义标头名称设为小写。

  2. 使用按字典顺序排序的代码点值,按标头名称对所有自定义标头排序。

  3. 移除 x-goog-encryption-keyx-goog-encryption-key-sha256 标头(如果存在)。这些标头包含敏感信息(不能包含在要签名的字符串中);但是,在使用生成的签名网址的任何请求中,仍然必须使用这些标头。

  4. 创建一个标头名称(带有逗号分隔的值列表)以消除重复标头名称。确保值之间没有空格,并确保英文逗号分隔列表的顺序与标头在请求中显示的顺序匹配。如需了解详情,请参阅 RFC 7230 第 3.2 节

  5. 将折叠空格或换行符(CRLF 或 LF)替换为一个空格。如需详细了解折叠空格,请参阅 RFC 7230 第 3.2.4 节

  6. 移除标头名称后面出现的冒号周围的所有空格。

  7. 向每个自定义标头附加换行符"\n" (U+000A)。

  8. 连接所有自定义标头。

规范资源

使用程序创建签名网址时,您会构造消息的“规范化资源”部分,要执行此操作,您需要连接请求所使用的资源路径(存储桶、对象和子资源)。在创建资源时,请牢记以下几点:

  • 规范资源是主机名后面的所有内容。例如,如果 Cloud Storage 网址为 https://storage.googleapis.com/example-bucket/cat-pics/tabby.jpeg,则规范资源为 /example-bucket/cat-pics/tabby.jpeg

  • 如果请求的范围限定为某个子资源(例如 ?cors),请将此子资源(包含问号)添加到字符串的末尾。

  • 确保逐字复制 HTTP 请求路径:也就是说,您应在您创建的字符串中包含所有网址编码(百分号)。此外,还要确保仅包含指定了子资源(例如 cors)的查询字符串参数。请勿包含 ?prefix?max-keys?marker?delimiter 等查询字符串参数。