最近更新时间:2022-12-30 15:47:52
使用对象存储服务(KS3) 时,可通过 RESTful API 对 KS3 发起 HTTP 匿名请求或 HTTP 签名请求,对于签名请求,KS3服务器端将会对请求发起者进行身份验证。
KS3提供V4和V2两种签名方式,推荐使用V4签名方式。KS3 V4签名兼容 AWS Signature Version 4,签名方法参见Authenticating Requests - AWS Signature Version 4。
注意:本文描述的是HTTP RESTful API 请求签名方式,如果您使用 SDK 进行开发,SDK中会包含签名计算方法,您无需单独计算签名。仅在您希望通过原始 API 进行开发时,需要根据本文所描述步骤进行签名计算。
创建V4签名的步骤简述如下,后面将详述各个步骤的操作方法。
用户可以通过以下几种方式来发送签名信息:
Authorization请求头示例如下(增加换行是为了方便阅读,实际为空字符串):
Authorization: KSS4-HMAC-SHA256
Credential=AKLTYS28X1sBSXCMRPMxU77t7A/20211129/SHANGHAI/ks3/kss4_request,
SignedHeaders=content-type;host;user-agent;x-kss-content-sha256;x-kss-date, Signature=6d9df5717ebb7cdeae7d08d817b80d6a90ca32320b07e46f30c64136eade9d48
组成字段说明如下:
字段名称 | 描述 |
---|---|
KSS4-HMAC-SHA256 |
用于签名的算法,固定值。 |
Credential | 用户的AccessKeyId和范围信息,范围信息包括请求日期、区域、服务、终止字符串kss4_request,格式如下: <your-access-key-id>/<date>/<region>/<service>/kss4_request 其中: date格式为YYYYMMDD。 region:参见Endpoint与Region的对应关系 中的Region英文名称 service:固定值为ks3 |
SignedHeaders | 已签名请求头的列表。该列表只需包含请求头名字,用分号分隔,必须全部小写,并按字符顺序对其进行排序,示例如下:host;range;x-amz-date |
Signature | 计算出的256位签名信息,以64个小写十六进制字符串形式表示。 |
有两种签名计算方式:
1)签名负载方式 - 用户可以选择计算整个负载(即请求体)的checksum,并将其包含在签名计算中。这种方式提高了安全性,但用户需要读取两次负载或将其缓冲在内存中。我们建议用户使用包含负载checksum的签名方式,以增强安全性。
2)无签名负载方式 - 在签名计算中不包括负载的checksum。
上述两种方式,都必须携带x-kss-content-sha256请求头,如果选择签名负载方式,请将x-kss-content-sha256请求头的值设置为负载的checksum值,否则将值设置为文本字符串 UNSIGNED-PAYLOAD。
下表描述了图中显示的方法,用户需要为这些函数实现代码。
功能 | 描述 |
---|---|
Lowercase() | 将字符串转换为小写。 |
Hex() | 小写16进制编码。 |
SHA256Hash() | 安全散列算法(SHA)加密散列函数。 |
HMAC-SHA256() | 使用签名密钥,根据SHA256算法计算出的签名值。 |
Trim() | 删除任何前导或尾随空格。 |
UriEncode() | URI编码每个字节。UriEncode()必须强制执行以下规则: URI编码除了下面字符之外的每个字节:‘A’ - ‘Z’,‘a’ - ‘z’,‘0’ - ‘9’,’ - ‘,’.’,’_‘和’〜’。 空格字符是保留字符,必须编码为“%20”(而不是“+”)。 每个URI编码字节由’%‘和两位十六进制值组成。 十六进制值中的字母必须为大写,例如“%1A”。 除了对象名之外,对正斜杠字符’/'进行编码。 例如,如果对象名称为photos/Jan/sample.jpg,则不对名称中的正斜杠进行编码。 重要建议用户编写自己的自定义UriEncode函数,以确保您的编码可以正常工作。 |
注意:以下代码是Java中的示例UriEncode()函数。
StringBuilder result = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') {
result.append(ch);
} else if (ch == '/') {
result.append(encodeSlash ? "%2F" : ch);
} else {
result.append(toHexUTF8(ch));
}
}
return result.toString();
}
将请求的内容(包括请求方法、URI、请求头等)组织为标准规范格式。伪代码如下:
CanonicalRequest = HTTPRequestMethod + '\n' + CanonicalURI + '\n' + CanonicalQueryString + '\n' + CanonicalHeaders + '\n' + SignedHeaders + '\n' + HexEncode(Hash(RequestPayload))
CanonicalQueryString是URI编码后的查询字符串参数。用户需要单独对参数名称和值进行URI编码。并需要按参数名称的字母顺序,对参数进行排序,排序在编码后进行。具有重复名称的参数应按值进行排序。例如,以大写字母 F 开头的参数名称排在以小写字母 b 开头的参数名称之前。
以下URI示例中的查询字符串是 prefix=somePrefix&marker=someMarker&max-keys=20:
http://examplebucket.ks3-cn-beijing.ksyuncs.com/?prefix=somePrefix&marker=someMarker&max-keys=20
CanonicalQueryString的构造方式如下(为了便于阅读,添加了换行符):
UriEncode("marker")+"="+UriEncode("someMarker")+"&"+
UriEncode("max-keys")+"="+UriEncode("20") + "&" +
UriEncode("prefix")+"="+UriEncode("somePrefix")
当请求的目标是子资源时,相应的查询参数的值设置为空字符串(“”)。例如,下面的请求用于设置bucket的ACL权限:
http://examplebucket.ks3-cn-beijing.ksyuncs.com/?acl
在这种情况下,CanonicalQueryString为:
UriEncode("acl") + "=" + ""
如果URI中不包含“?”,则请求中不存在查询字符串,此时将CanonicalQueryString设置为空字符串(“”),但仍需要包含“\ n”。
CanonicalHeaders是请求头的列表。请求头名称转成小写,请求头名称和值之间用冒号(":")分隔,各行之间用换行符(“\ n”)分隔,并对请求头名称按字母顺序进行排序,示例如下:
Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n"
Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n"
...
Lowercase(<HeaderNameN>)+":"+Trim(<value>)+"\n"
CanonicalHeaders列表必须包括以下内容:
除了上述列出的必须增加的头,只计算SignedHeaders中包含的头。注意,Authorization不参与签名内容计算。
以下是CanonicalHeaders 的示例,请求头名称为小写并已排序。
host:bucket-name.ks3-cn-beijing.ksyuncs.com
x-kss-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-kss-date:20211130T070023Z
为防止用户请求头被篡改,将参与签名运算的请求头加入到SignedHeaders中。SignedHeaders是按字母顺序排序的,以分号分隔的小写请求头名称列表。列表中的请求头与用户在CanonicalHeaders字符串中包含的请求头相同。
格式为:
Lowercase(<HeaderName1>)+";"+Lowercase(<HeaderName2>)+";"+...+Lowercase(<HeaderNameN>)
例如,对于前面的示例,SignedHeaders的值为:
host;x-kss-content-sha256;x-kss-date
注意:时间戳(x-kss-date或Date请求头)15分钟内有效,没有权限的用户可通过截获已签名的请求,并篡改SignedHeaders中没有包含的部分来伪造请求,所以为确保您的数据安全,建议您签名所有请求头和请求体。
HashedPayload是请求体的SHA256哈希的十六进制值。
如果请求中没有请求体,则计算空字符串的哈希值,如下所示:
Hex(SHA256Hash(""))
哈希返回以下值:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
例如,当用户使用PUT请求上传对象时,用户可以在请求体中提供对象数据。使用GET请求检索对象时,没有请求体,所以计算空字符串的哈希。
x-kss-content-sha256 请求头是必须的,取值范围如下:
值 | 描述 |
---|---|
HexEncode(Sha256Hash(RequestPayload)) | 请求体经过哈希处理的以小写十六进制字符串表示形式 |
UNSIGNED-PAYLOAD | 忽略请求正文的哈希校验 |
STREAMING-KSS4-HMAC-SHA256-PAYLOAD | chunk传输校验,暂不支持 |
计算方法为:
HashedPayload = Lowercase(HexEncode(SHA256Hash(requestPayload)))
使用 SHA256 哈希函数对请求体创建哈希值。V4签名不需要您使用特定字符编码来对负载中的文本进行编码。
如果负载为空,则使用空字符串作为哈希函数的输入。
待签名的字符串格式如下:
"KSS4-HMAC-SHA256" + "\n" + <RequestDateTime> + "\n" + <CredentialScope> + "\n" + Hex(SHA256Hash(<CanonicalRequest>))
date.Format(<YYYYMMDD>) + "/" + <region> + "/" + <service> + "/kss4_request"
使用 secretKey作为初始哈希操作的密钥,对请求日期、区域和服务执行一系列加密哈希操作(HMAC 操作),从而生成签名密钥。伪代码如下:
kSecret = your Secret Key
kDate = HMAC("KSS4" + kSecret, Date)
kRegion = HMAC(kDate, Region)
kService = HMAC(kRegion, Service)
SigningKey = HMAC(kService, "kss4_request")
最终签名是使用签名密钥作为密钥,对待签名字符串计算得到HMAC-SHA256哈希值。伪代码如下:
HMAC-SHA256(SigningKey, StringToSign)
请注意,哈希过程中所使用的日期的格式为 YYYYMMDD(例如,20150830),不包括时间。
确保以正确的顺序为您要使用的编程语言指定 HMAC 参数。在此示例中,密钥是第1个参数,数据 (消息) 是第2个参数,但您使用的函数可能以不同顺序指定密钥和数据。
使用摘要 (二进制格式) 来派生密钥。大多数语言都有用来计算二进制格式哈希(通常称为摘要)或十六进制编码哈希(称为十六进制摘要)的函数。派生密钥需要使用二进制格式摘要。
示例:
HMAC(HMAC(HMAC(HMAC("KSS4" + kSecret,"20211129"),"BEIJING"),"ks3"),"kss4_request")
在计算签名后,将其添加到请求的 HTTP 请求头Authorization中,伪代码如下:
Authorization: <algorithm> Credential=<ak>/<credential_scope>, SignedHeaders=<SignedHeaders>, Signature=<signature>
以下是使用V4签名的示例。示例中使用的访问密钥如下:
参数 | 值 |
---|---|
KSSAccessKeyId |
AKLTA6qLnuowT6KzKybUQNC0Tw |
KSSSecretAccessKey |
OCd5HzFDU1YDUG6eTHASvdt1RRn5bqKNKdl8JxuFrYne+bazX7gmoYUG73XjJ/d2sg== |
Bucket名称:examplebucket。访问的域名是ks3-cn-beijing.ksyuncs.com, region是BEIJING
从存储桶 examplebucket中获取对象1.txt的前5个字节。请求如下:
GET /1.txt HTTP/1.1
x-kss-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Authorization: SignatureToBeCalculated
x-kss-date: 20211130T061712Z
Range: bytes=0-4
Host: examplebucket.ks3-cn-beijing.ksyuncs.com
由于此GET请求不提供任何请求体内容,因此该 x-amz-content-sha256请求头的值是空请求体的哈希值。以下步骤显示Authorization请求头的计算的方法。
1)StringToSign
a.创建规范请求
GET
/1.txt
host:examplebucket.ks3-cn-beijing.ksyuncs.com
range:bytes=0-4
x-kss-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-kss-date:20211130T062035Z
host;range;x-kss-content-sha256;x-kss-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
其中,最后一行是空请求体的hash值。第三行是空,因为此请求不包含请求参数。
b.待签名字符串
KSS4-HMAC-SHA256
20211130T062035Z
20211130/BEIJING/ks3/kss4_request
e124a1d2400e6c08fdfc78c02a62f8a8900d67d577ffedc1820347794a106dfe
2)生成签名密钥
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("KSS4" + "<YourSecretAccessKey>","20211130"),"BEIJING"),"ks3"),"kss4_request")
3)计算后的签名
0b6e5f3e77ca9e0201c4033916a796c232ebe244c2a42f23493d7aba45217f09
4)Authorization请求头
Authorization: KSS4-HMAC-SHA256
Credential=AKLTA6qLnuowT6KzKybUQNC0Tw/20211130/BEIJING/ks3/kss4_request,
SignedHeaders=host;range;x-kss-content-sha256;x-kss-date,
Signature=0b6e5f3e77ca9e0201c4033916a796c232ebe244c2a42f23493d7aba45217f09
在存储桶中上传对象1.txt。
PUT /1.txt HTTP/1.1
x-kss-content-sha256: 7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9
Authorization: SignatureToBeCalculated
x-kss-date: 20211130T062938Z
x-kss-storage-class: STANDARD
Host: examplebucket.ks3-cn-beijing.ksyuncs.com
Content-Length: 12
hello world!
以下步骤显示Authorization请求头的计算的方法。
1)StringToSign
a.创建规范请求
PUT
/1.txt
content-length:12
host:examplebucket.ks3-cn-beijing.ksyuncs.com
x-kss-content-sha256:7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9
x-kss-date:20211130T062938Z
x-kss-storage-class:STANDARD
content-length;host;x-kss-content-sha256;x-kss-date;x-kss-storage-class
7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9
其中,第三行是空,因为此请求不包含请求参数。最后一行是请求体的hash值,它应该与x-kss-content-sha256 请求头的值相同。
b.待签名字符串
KSS4-HMAC-SHA256
20211130T062938Z
20211130/BEIJING/ks3/kss4_request
35bc694c8cc1176f94aa68fcb2ccc01303d8190c4de88f76c5989cbfaecdb626
2)生成签名密钥
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("KSS4" + "<YourSecretAccessKey>","20211130"),"BEIJING"),"ks3"),"kss4_request")
3)计算后的签名
87e3404b5aa78b92f1453ee16a9274c52e42b414eab576e8d25c212bb53dc0b0
4)Authorization请求头
Authorization: KSS4-HMAC-SHA256
Credential=AKLTA6qLnuowT6KzKybUQNC0Tw/20211130/BEIJING/ks3/kss4_request,
SignedHeaders=content-length;host;x-kss-content-sha256;x-kss-date;x-kss-storage-class,
Signature=87e3404b5aa78b92f1453ee16a9274c52e42b414eab576e8d25c212bb53dc0b0
列出存储空间 examplebucket中的对象,prefix设置为“1”,最多返回2个对象。请求如下:
GET /?max-keys=2&prefix=1 HTTP/1.1
x-kss-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855Authorization: SignatureToBeCalculated
x-amz-date: 20211130T063717Z
Host: examplebucket.ks3-cn-beijing.ksyuncs.com
以下步骤显示Authorization请求头的计算的方法。
1)StringToSign
a.创建规范请求
GET
/
max-keys=2&prefix=1
host:examplebucket.ks3-cn-beijing.ksyuncs.com
x-kss-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-kss-date:20211130T063717Z
host;x-kss-content-sha256;x-kss-date
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
其中,最后一行是空请求体的hash值。
b.待签名字符串
KSS4-HMAC-SHA256
20211130T063717Z
20211130/BEIJING/ks3/kss4_request
ec5654b7a599933116a221760119535b4c75552ec6c629d69580c826a3f77e76
2)生成签名密钥
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("KSS4" + "<YourSecretAccessKey>","20211130"),"BEIJING"),"ks3"),"kss4_request")
3)计算后的签名
2db9781b81a2b21852964b2dec0b07f58d0d1355fdedb27a9513294cb5776f9b
4)Authorization请求头
Authorization: KSS4-HMAC-SHA256
Credential=AKLTA6qLnuowT6KzKybUQNC0Tw/20211130/BEIJING/ks3/kss4_request,
SignedHeaders=host;x-kss-content-sha256;x-kss-date,
Signature=2db9781b81a2b21852964b2dec0b07f58d0d1355fdedb27a9513294cb5776f9b
用户可以使用查询字符串参数来发送签名信息,示例如下。
https://examplebucket.ks3-cn-beijing.ksyuncs.com/test.txt
?X-Kss-Algorithm=KSS4-HMAC-SHA256
&X-Kss-Credential=<your-access-key-id>/<yyyymmdd>/<region>/ks3/kss4_request
&X-Kss-Date=20211129T065239Z
&X-Kss-Expires=86400
&X-Kss-SignedHeaders=host
&X-Kss-Signature=<signature-value>
在示例URL中,请注意以下事项:
&X-Kss-Credential=<your-access-key-id>%2F20211129%2F<region>%2Fks3%2Fkss4_request
各参数含义说明如下。
参数名称 | 描述 |
---|---|
X-Kss-Algorithm | 签名算法:KSS4-HMAC-SHA256 |
X-Kss-Credential | 用户的accessKeyId和范围信息,范围信息包括请求日期、区域、服务、终止字符串kss4_request,格式如下:<your-access-key-id>/<date>/<region>/<service>/kss4_request其中:date格式为YYYYMMDD。region:参阅Region英文名称 service:为ks3 |
X-Kss-Date | 日期和时间格式必须遵循ISO 8601标准,并且必须使用“yyyyMMddTHHmmssZ”格式进行格式化。例如,如果日期和时间是“08/01/2018 15:32:41.982-700”,则必须首先将其转换为UTC(协调世界时),然后转换为“20180801T083241Z”。请求的时间戳不能大于(服务端时间戳+15分钟) |
X-Kss-Expires | 过期时间,单位秒。时间范围为1-604800(7天)。例如,86400(表示24小时)。请求时间戳+过期时间应大于服务端时间戳。 |
X-Kss-SignedHeaders | 列出用于计算签名的标头。签名计算中需要以下标头: HTTP Host请求头。 x-kss-*请求头。 |
X-Kss-Signature | 签名结果 |
签名过程如下图所示。
使用参数的签名过程与使用请求头的签名过程类似,说明如下:
通过创建签名URL的方式,与其他人共享examplebucket中1.txt对象,过期时间设置为7天(604800秒)。以GET请求为例:
GET
http://examplebucket.ks3-cn-beijing.ksyuncs.com/1.txt
?X-Kss-Algorithm=KSS4-HMAC-SHA256
&X-Kss-Credential=AKLTA6qLnuowT6KzKybUQNC0Tw%2F20211130%2FBEIJING%2Fks3%2Fkss4_request
&X-Kss-Date=20211130T075703Z
&X-Kss-Expires=604800
&X-Kss-SignedHeaders=host
&X-Kss-Signature=<signature-value>
以下步骤首先说明如何计算签名和构建预签名URL。示例中使用的访问密钥如下:
参数 | 值 |
---|---|
KSSAccessKeyId |
AKLTA6qLnuowT6KzKybUQNC0Tw |
KSSSecretAccessKey |
OCd5HzFDU1YDUG6eTHASvdt1RRn5bqKNKdl8JxuFrYne+bazX7gmoYUG73XjJ/d2sg== |
1)StringToSign
a. 创建规范请求(以GET请求为例)
GET
/1.txt
X-Kss-Algorithm=KSS4-HMAC-SHA256&X-Kss-Credential=AKLTA6qLnuowT6KzKybUQNC0Tw%2F20211130%2FBEIJING%2Fks3%2Fkss4_request&X-Kss-Date=20211130T075703Z&X-Kss-Expires=604800&X-Kss-SignedHeaders=host
host:examplebucket.ks3-cn-beijing.ksyuncs.com
host
UNSIGNED-PAYLOAD
b. 待签名字符串
KSS4-HMAC-SHA256
20211130T075703Z
20211130/BEIJING/ks3/kss4_request
19469bd87d923505aa26d4596f44ffc24b0a1bc65c2a15c149bfd31621d06488
2)生成签名密钥
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("KSS4" + "<YourSecretAccessKey>","20211130"),"BEIJING"),"ks3"),"kss4_request")
3)计算后的签名
f6c0682252a278ca84ea2f4acbff6cefe15d9529b3ef678ee3d0ec452c697b00
4)预签名URL
http://examplebucket.ks3-cn-beijing.ksyuncs.com/1.txt?X-Kss-Algorithm=KSS4-HMAC-SHA256&X-Kss-Credential=AKLTA6qLnuowT6KzKybUQNC0Tw%2F20211130%2FBEIJING%2Fks3%2Fkss4_request&X-Kss-Date=20211130T075703Z&X-Kss-Expires=604800&X-Kss-SignedHeaders=host&X-Kss-Signature=f6c0682252a278ca84ea2f4acbff6cefe15d9529b3ef678ee3d0ec452c697b00
对于Post Object请求,HTML 表单中必须包含 Policy 和 Signature 信息。
计算 Signature 的具体流程为:
表单项 | 说明 |
---|---|
policy | 表单上传安全策略 |
x-kss-algorithm | 签名算法: KSS4-HMAC-SHA256 |
x-kss-credential | 签名范围:格式为<your-access-key-id>/<date>/<KS3-region>/<KS3>/kss4_request |
x-kss-date | 请求时间:时间格式为 yyyyMMddTHHmmssZ (X-Kss-Date<=now+15m) 请求的时间戳不能大于(服务器时间戳+15m) |
x-kss-signature | 签名结果(计算签名时queryString不包含X-Kss-Signature) |
您在凭证范围中使用的日期必须与您的请求的日期匹配。您可以用多种方法将日期包括在请求中。您可以使用 date 请求头或 x-kss-date请求头,或者将 x-kss-date作为查询参数包含在内。
时间戳必须采用 UTC 表示,并具有以下 ISO 8601 格式:YYYYMMDD’T’HHMMSS’Z’。例如,20150830T123600Z 是有效时间戳。请勿在时间戳中包含毫秒。
KS3先检查时间戳的x-kss-date请求头或参数,如果无法找到 x-kss-date,则将寻找 date 请求头。 检查八位数字字符串形式的凭证范围,表示请求的年 (YYYY)、月 (MM) 和日 (DD)。例如,如果 x-kss-date 标头值为 20111015T080000Z,并且凭证范围的日期部分为 20111015,则允许身份验证过程继续执行。如果日期不匹配,则拒绝请求,即使时间戳距离凭证范围中的日期仅有数秒之差也是如此。例如,将拒绝其x-kss-date请求头值为 20151014T235959Z 且凭证范围包括日期 20151015 的请求。
KS3同时支持KS3 V4和AWS V4签名, 如果签名算法为KSS4-HMAC-SHA256,则根据KS3 V4进行签名,如果签名算法为AWS4-HMAC-SHA256,则根据AWS V4签名。两种签名方式对比如下:
项目 | S3 | KS3 |
---|---|---|
请求头前缀 | x-amz- | x-kss- |
queryString前缀 | X-Amz- | X-Kss- |
协议 | AWS4 | KSS4 |
服务名称 | s3 | ks3 |
固定值 | aws4_request | kss4_request |
纯净模式