在Header中包含V4签名(推荐)

更新时间:2025-03-25 08:18:33

向 OSS 发起请求时,添加包含 V4 签名的 Authorization 请求头(Header),以确保请求能够通过身份验证。优先使用 OSS 提供的 SDK 发起请求,因为 SDK 已集成复杂的 V4 签名算法。只有在无法使用 SDK 时,才需要参考本文自行实现 V4 签名算法。

SDK 签名实现

如果需要自行实现 V4 签名算法,优先参考 SDK 的 V4 签名实现。

Authorization 请求头

向 OSS 发起请求时,需在 Authorization 请求头中包含签名,用于验证请求。

Authorization 请求头格式如下:

Authorization: OSS4-HMAC-SHA256 Credential=<AccessKeyId>/<SignDate>/<SignRegion>/oss/aliyun_v4_request, AdditionalHeaders=<AdditionalHeadersVal>, Signature=<SignatureVal>

Authorization 请求头说明如下:

组成部分

说明

组成部分

说明

OSS4-HMAC-SHA256

用于指定计算签名的算法。当您使用 V4 签名进行身份验证时,必须提供此值。

该字符串指定了 OSS V4 签名版本(OSS4)和签名算法(HMAC-SHA256)。

Credential

您的AccessKey ID和范围信息(包括用于计算签名的日期、地域和云产品)。当您使用 V4 签名进行身份验证时,必须提供该字段。

Credential的格式如下:

<AccessKeyId>/<SignDate>/<SignRegion>/oss/aliyun_v4_request

其中:

  • <AccessKeyId>:您的AccessKey ID。这是一个唯一的标识符,用于验证请求的发起者身份。

  • <SignDate>:签名日期,以 YYYYMMDD 格式表示。

  • <SignRegion>: 请求所使用的地域ID,例如 cn-hangzhou。

  • oss:固定字符串,标识请求所针对的服务是阿里云对象存储OSS。

  • aliyun_v4_request:固定字符串,指定请求的签名版本为V4。

AdditionalHeaders

用于指定计算签名过程中可选的请求头,仅包含小写的头名称,并按字典序排序,以分号(;)分隔。

该字符串的示例如下:

host;x-oss-content-sha256;x-oss-date

Signature

计算得到的签名。当您使用 V4 签名进行身份验证时,必须提供该字段。

用 64 个小写的十六进制数字表示的256 位的签名值示例如下:

3938**********************************dcdc

签名计算

OSS 收到请求后,会计算签名,并与 Authorization 请求头中的签名对比。如果一致,则请求成功;否则,请求失败。

签名计算过程

签名计算过程可以分为以下三步:

  1. 构造规范化请求:按照 OSS 签名定义的规范,对请求进行格式化,得到规范化请求。

  2. 构造待签名字符串:对规范化请求进行统一计算处理,得到待签名字符串。

  3. 计算签名:对 AccessKey Secret 进行多步哈希运算生成派生密钥,然后使用派生密钥对待签名字符串进行计算,最终得到签名。

构造规范化请求

规范化请求格式如下:

HTTP Verb + "\n" +
Canonical URI + "\n" +
Canonical Query String + "\n" +
Canonical Headers + "\n" +
Additional Headers + "\n" +
Hashed PayLoad

规范化请求说明如下:

参数

说明

参数

说明

HTTP Verb

HTTP 请求方法,包含PUT、GET、POST、HEAD、DELETE、OPTIONS等。

Canonical URI

URI 编码的资源路径。资源路径不包含查询字符串,其中正斜线(/)不需要编码。

  • 如果请求目标为OSS服务:

    • 资源路径:/

    • 规范化的资源路径:UriEncode("/")

  • 如果请求目标为Bucket:

    • 资源路径:/examplebucket/

    • 规范化的资源路径:UriEncode("/examplebucket/")

  • 如果请求目标为Bucket中的Object:

    • 资源路径:/examplebucket/exampleobject

    • 规范化的资源路径:UriEncode("/examplebucket/exampleobject")

Canonical Query String

按字典排序的URI编码的查询参数。

  • 如果查询参数包含参数名称和值,先对每个参数的名称和值分别进行 URI 编码,然后按照参数名称的字典顺序对参数进行排序。注意,排序是在编码之后进行的。使用 = 连接编码后的名称和值,并使用 & 连接不同的参数。

    • 查询参数:prefix=somePrefix&marker=someMarker&max-keys=20

    • 规范化的查询参数:

      UriEncode("marker")+"="+UriEncode("someMarker")+"&"+UriEncode("max-keys")+"="+UriEncode("20")+"&"+UriEncode("prefix")+"="+UriEncode("somePrefix")
  • 如果查询参数只包含参数名称,只对参数名称进行 URI 编码,并按照 参数名称= 的格式构建格式化查询。

    • 查询参数:?acl

    • 规范化的查询参数:UriEncode("acl") + "=" + ""

  • 如果没有查询参数,即请求的 URI 中不包含 ?,则规范化的查询字符串设为空字符串("")。

Canonical Headers

请求头列表。每个请求头中的keyvalue通过冒号:分隔,请求头与请求头之间通过换行符分隔。请求头的key必须小写,value必须经过Trim(去除头尾的空格)。按请求头中key的字典序进行排列。

格式如下:

Lowercase(<HeaderName1>) + ":" + Trim(<value>) + "\n"
Lowercase(<HeaderName2>) + ":" + Trim(<value>) + "\n"
...
Lowercase(<HeaderNameN>) + ":" + Trim(<value>) + "\n"

示例如下:

host:cname.com
x-oss-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-oss-date:20231203T121212Z

Canonical Headers包含以下三类:

  • 必须存在且参与签名的:

    • host

    • x-oss-content-sha256:目前只支持取值为UNSIGNED-PAYLOAD

  • 如果存在则参与签名的:

    • Content-Type

    • Content-MD5

    • x-oss-*:例如,通过 STS AK 来访问的时候,SecurityToken 通过 x-oss-security-token:security-token 来描述。例如,请求时间通过x-oss-date来描述,格式必须为ISO8601标准时间格式,例如20231203T121212Z

  • Additional Headers 指定必须存在且参与签名的 Header。

Additional Headers

除了Content-TypeContent-MD5x-oss-*以外,其他需要加入签名的Header。所有的Header必须是小写,且按照字典序排列。

示例如下:

content-length;host

Hashed PayLoad

请求负载的 SHA256 哈希值的十六进制表现形式。目前只支持取值为UNSIGNED-PAYLOAD,即在签名过程中省略对请求体(Payload)的哈希计算,从而简化大文件传输的签名过程。

构造待签名字符串

待签名字符串格式如下:

"OSS4-HMAC-SHA256" + "\n" +
TimeStamp + "\n" +
Scope + "\n" +
Hex(SHA256Hash(<CanonicalRequest>))

待签名字符串说明如下:

参数

说明

参数

说明

OSS4-HMAC-SHA256

签名哈希算法,取值必须是OSS4-HMAC-SHA256

TimeStamp

当前UTC时间,格式必须是ISO8601,例如20250320T083322Z

Scope

获取派生密钥的参数集。该参数集指明了日期、地域和服务。因此,通过派生密钥计算的签名只能在指定的日期、地域和服务中有效。

格式如下:

<SigningDate>/<SigningRegion>/oss/aliyun_v4_request

说明如下:

  • SigningDate:参与签名的日期,以 YYYYMMDD 格式表示。

  • SigningRegion:参与签名所使用的地域ID,例如 cn-hangzhou

  • oss:参与签名的服务名称,固定为oss

  • aliyun_v4_request:参与签名的版本,固定为aliyun_v4_request

CanonicalRequest

构造的规范化请求。

计算签名

计算签名分为以下两步:

  1. 计算 SigningKey

    DateKey = HMAC-SHA256("aliyun_v4" + SK, Date);
    DateRegionKey = HMAC-SHA256(DateKey, Region);
    DateRegionServiceKey = HMAC-SHA256(DateRegionKey, "oss");
    SigningKey = HMAC-SHA256(DateRegionServiceKey, "aliyun_v4_request");
    • SK:参与签名的AccessKey Secret。

    • Date:参与签名的日期,以 YYYYMMDD 格式表示,必须和待签名字符串中的Scope中的SigningDate一致。

    • Region:参与签名所使用的地域ID,例如 cn-hangzhou,必须和待签名字符串中的Scope中的SigningRegion一致。

  2. 使用 SigningKey 与待签名字符串计算 Signature

    Signature = HEX(HMAC-SHA256(SigningKey, StringToSign))

签名计算图解

签名计算过程如下图所示:

image

签名计算示例

以 PutObject 为例,进行签名计算。

签名计算参数

参数

参数

AccessKeyId

LTA*********************1aH

AccessKeySecret

R6v**************************C7D

Timestamp

20250320T114331Z

Bucket

examplebucket

Object

exampleobject

Region

cn-hangzhou

签名计算过程示例

  1. 构造规范化请求。

    PUT
    /examplebucket/exampleobject
    
    content-md5:ICy5YqxZB1uWSwcVLSNLcA==
    content-type:text/plain
    host:examplebucket.oss-cn-hangzhou.aliyuncs.com
    x-oss-content-sha256:UNSIGNED-PAYLOAD
    x-oss-date:20250320T114331Z
    x-oss-meta-author:alice
    x-oss-meta-magic:abracadabra
    
    content-md5;content-type;host;x-oss-content-sha256;x-oss-date;x-oss-meta-author;x-oss-meta-magic
    UNSIGNED-PAYLOAD
  2. 构造待签名字符串。

    OSS4-HMAC-SHA256
    20250320T114331Z
    20250320/cn-hangzhou/oss/aliyun_v4_request
    4810d58ff8570752af9be07fed060cfa50affdfafd1feec5b52c3dbf8cce0bf2
  3. 计算签名。

    1. 计算SigningKey。

      7469f9*********************************fd24
    2. 计算Signature。

      618b9c********************************9c6dc
  • 本页导读 (1)
  • SDK 签名实现
  • Authorization 请求头
  • 签名计算
  • 签名计算过程
  • 构造规范化请求
  • 构造待签名字符串
  • 计算签名
  • 签名计算图解
  • 签名计算示例