POST V2签名说明
POST签名是指使用POST方式上传文件时,要求每个请求都必须附带一个签名(Signature)。POST V2签名是通过访问密钥(Secret Access Key)对一系列请求参数(上传策略policy等)进行加密计算得到的。当请求发送时,会验证签名的合法性,只有签名验证成功的请求才会被接受,否则请求将被拒绝。
POST V2签名表单独有参数
POST V2签名除了POST上传对象中说明的公共表单元素外,会有一些独有的表单元素:
参数 | 参数类型 | 说明 |
---|---|---|
AWSAccessKeyId | String | Bucket拥有者的Access Key ID,当Bucket为非public-read-write或者提供了Policy(或Signature)表单域时,必须提供AWSAccessKeyId表单域 |
Signature | String | 根据AccessKey Secret和Policy计算的签名信息,验证该签名信息从而验证该Post请求的合法性。注意: 当Bucket为非public-read-write或者提供了AWSAccessKeyId(或Policy)表单域时,必须提供Signature表单域,同时表单域的值对大小写敏感,但是表单域对大小写不敏感 |
Policy说明
Policy表单域是一种安全策略,若请求不包含Policy,则只能访问public-read-write的Bucket, 当Bucket为非public-read-write或者提供了AccessKeyId(或Signature)表单域时,必须提供Policy表单域 。 Policy由JSON格式来定义,可以通过多项参数来限制上传的相关操作,比如允许上传的Bucket、Key前缀等。
其中,policy中有两个字段是必须的:
- expiration:指定policy的过期时间(ISO8601 GMT格式)。例如指定为2024-12-16T13:00:00.000Z,表示必须在2024年12月16日13点之前发起POST请求。
- conditions:指定POST请求表单域的合法值。
conditions表
参数 | 参数类型 | 必选 | 说明 | 匹配方式 | 示例 |
---|---|---|---|---|---|
bucket | String | 否 | 存储桶名称。 | bucket | {"bucket": "examplebucket"} |
key | String | 否 | 上传对象的名称。 | eq、starts-with、in和not-in | ["eq", "$key", "ExampleObject"] |
content-length-range | String | 否 | 上传对象时的最小以及最大允许的大小,单位是字节。 | content-length-range | ["content-length-range", 1, 10] |
success_action_status | String | 否 | 上传成功后的返回状态码。 | eq、starts-with、in和not-in | ["eq", "$success_action_status", "201"] |
content-type | String | 否 | 限制对象的文件类型。 | eq、starts-with、in和not-in | ["in", "$content-type", ["image/jpg", "image/png"]] |
cache-control | String | 否 | 缓存控制。 | eq、starts-with、in和not-in | ["not-in", "$cache-control", ["no-cache"]] |
conditions匹配方式表
匹配方式 | 说明 |
---|---|
eq | 精确匹配。比如 ["eq", "$key", "ExampleObject"],则表单域中指定key的值必须为ExampleObject:{"key": "ExampleObject"}。 |
starts-with | 前缀匹配。比如 ["starts-with", "$key", "aaa/bbb"],则表单域中指定key的值必须以aaa/bbb开始:{"key": "aaa/bbb/ccc"}。 |
in | 包含匹配。比如 ["in", "$content-type", ["image/jpg", "image/png"]],则PostObject接口上传图片对象时,允许image/jpg或image/png格式的图片:{"content-type": "image/jpg"}。 |
not-in | 排除匹配。比如 ["not-in", "$content-type", ["image/jpg", "image/png"]],则PostObject接口上传图片对象时,不能允许image/jpg或image/png格式的图片对象。 |
示例
{
"expiration": "2024-12-16T13:00:00.000Z",
"conditions": [
{"bucket": "testbucket"},
["content-length-range", 1, 10],
["eq", "$success_action_status", "201"],
["starts-with", "$key", "aaa/bbb/"]
]
}
POST V2签名生成规则
Signature形式
Base64(HmacSHA1(SecretAccessKey,Base64(PolicyJSON)))
签名步骤
- 第一步:创建utf-8编码的policy
- 第二步:构造签名字符串,在POST V2签名中,StringToSign是policy的Base64编码字符串
- 第三步:计算签名Signature,生成最终的签名时需要使用SecretAccessKey对StringToSign进行签名,该签名的计算方式为
Base64(HmacSHA1(SecretAccessKey,StringToSign))
生成POST V2签名参数代码示例
这里提供Python示例代码展示POST V2签名的计算过程:
import base64
import hmac
import hashlib
import json
def calculate_signature(string_to_sign, secret_key):
secret_key_bytes = bytes(secret_key, 'utf-8')
string_to_sign_bytes = bytes(string_to_sign, 'utf-8')
signature = hmac.new(secret_key_bytes, string_to_sign_bytes, hashlib.sha1).digest()
return base64.b64encode(signature).decode('utf-8')
def main():
access_key = "访问密钥ID"
secret_key = "私有访问密钥"
bucket = "testbuck"
key = "testobj"
# 创建 policy
policy_json = {
"expiration": "2024-12-16T13:00:00.000Z",
"conditions": [
{"bucket": bucket},
["starts-with", "$key", key]
]
}
# 创建签名字符串
string_to_sign = base64.b64encode(json.dumps(policy_json).encode('utf-8')).decode('utf-8')
# 计算签名
signature = calculate_signature(string_to_sign, secret_key)
print("key:", key)
print("AWSAccessKeyId:", access_key)
print("policy:", string_to_sign)
print("signature:", signature)
if __name__ == '__main__':
main()
输出的结果:
key: testobj
AWSAccessKeyId: 访问密钥ID
policy: eyJleHBpcmF0aW9uIjogIjIwMjQtMTItMTRUMTM6MDA6MDAuMDAwWiIsICJjb25kaXRpb25zIjogW3siYnVja2V0IjogInRlc3RidWNrIn0sIFsic3RhcnRzLXdpdGgiLCAiJGtleSIsICJ0ZXN0b2JqIl1dfQ==
signature: X2g5gF2cW1wjejnF4DQoUXg1z2s=