POST签名是指在使用PostObject上传方式时,为保证上传请求的安全性,OSS要求每个上传请求都携带一个签名(Signature)。在POST V1签名中,Signature是通过访问密钥(AccessKey Secret)对一系列请求参数(包括上传策略policy、到期时间等)进行加密计算得出。应用服务器生成签名后,将其与上传策略policy等信息一并提供给客户端,客户端使用这些信息构造上传请求。OSS收到上传请求后会验证签名的有效性,只有签名验证通过的请求会被接受,签名验证未通过的请求将被拒绝。
OSS支持更安全的V4签名算法,建议您使用V4签名。更多信息,请参见V4签名。
POST签名介绍
HTTP POST请求支持使用V1签名算法,表单和policy扮演着关键角色,用于确保上传请求的安全性和合规性。
表单
表单是POST请求中实际携带的字段集合,用于传递文件本身及其相关的元数据信息。以下是POST V1签名独有的表单元素,其他公共表单元素,请参见PostObject表单元素。
字段 | 类型 | 描述 |
OSSAccessKeyId | 字符串 | 访问密钥中的AccessKey ID。 默认值:无
重要 |
Signature | 字符串 | 根据AccessKey Secret和policy计算的签名信息,OSS通过签名信息验证POST请求的合法性。更多信息,请参见PostObject。 默认值:无 重要
|
policy
policy表单域是一种安全策略,用于定义用户通过HTML表单上传文件到OSS时的权限限制和约束条件。policy表单域通过JSON格式定义,通过多项参数限制上传操作,例如允许上传的Bucket名称、Object前缀、有效期、允许的HTTP方法、上传内容的大小限制、内容类型限制等。
policy中必须包含expiration和conditions字段。
{
"expiration": "2023-12-03T13:00:00.000Z",
"conditions": [
{"bucket": "examplebucket"},
["content-length-range", 1, 10],
["eq", "$success_action_status", "201"],
["starts-with", "$key", "user/eric/"],
["in", "$content-type", ["image/jpg", "image/png"]],
["not-in", "$cache-control", ["no-cache"]]
]
}
policy详细说明如下:
expiration
用于指定policy的过期时间,以ISO8601 GMT时间表示。例如指定为
2023-12-03T13:00:00.000Z
,表示必须在2023年12月03日13点之前发起POST请求。conditions
用于指定POST请求表单域的合法值。
字段
类型
是否必选
描述
Conditions匹配方式
bucket
字符串
否
Bucket名称。
bucket
content-length-range
字符串
否
上传Object的最小和最大允许大小,单位为字节。
content-length-range
success_action_status
字符串
否
上传成功后的返回状态码。
eq、starts-with、in和not-in
key
字符串
否
上传的Object名称。
eq、starts-with、in和not-in
content-type
字符串
否
限制上传的文件类型。
eq、starts-with、in和not-in
cache-control
字符串
否
指定Object的缓存行为。
eq、starts-with、in和not-in
签名计算过程
创建utf-8编码的policy。
构造StringToSign。
将policy进行Base64编码,生成一个安全传输的字符串,作为待签名字符串(StringToSign)。
计算Signature。
使用AccessKeySecret对要签名的字符串进行签名,签名方法为
Signature = base64(hmac-sha1(AccessKeySecret,base64(policy)))
。
POST签名计算完整示例代码
以上述提供的policy为例,通过Java示例代码演示POST签名计算的完整过程。
import org.apache.commons.codec.binary.Base64;
public class Demo {
public static void main(String[] args) {
// 运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_SECRET。
String accessKeySecret = System.getenv().get("OSS_ACCESS_KEY_SECRET");
// 步骤1:创建policy。
String policy = "{\n" +
" \"expiration\": \"2023-12-03T13:00:00.000Z\",\n" +
" \"conditions\": [\n" +
" {\"bucket\": \"examplebucket\"},\n" +
" [\"content-length-range\", 1, 10],\n" +
" [\"eq\", \"$success_action_status\", \"201\"],\n" +
" [\"starts-with\", \"$key\", \"user/eric/\"],\n" +
" [\"in\", \"$content-type\", [\"image/jpg\", \"image/png\"]],\n" +
" [\"not-in\", \"$cache-control\", [\"no-cache\"]]\n" +
" ]\n" +
"}";
// 步骤2:构造待签名字符串(StringToSign)。
String stringToSign = new String(Base64.encodeBase64(policy.getBytes()));
// 步骤3:计算Signature。
String signature = com.aliyun.oss.common.auth.ServiceSignature.create().computeSignature(accessKeySecret, stringToSign);
System.out.println("signature:" + signature);
}
}
返回结果如下:
signature:hR2cJnoG9uzrZLDAmrfOtUjtkSM=