POST V1签名

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。

默认值:无

    重要
    • 当Bucket ACL为公共读或者私有时,必须提供OSSAccessKeyId表单域。

    • 在已存在Signature、policy表单域的情况下,必须提供OSSAccessKeyId表单域。

Signature

字符串

根据AccessKey Secret和policy计算的签名信息,OSS通过签名信息验证POST请求的合法性。更多信息,请参见PostObject

默认值:无

重要
  • 当Bucket ACL为公共读或者私有时,必须提供Signature表单域。

  • 在已存在OSSAccessKeyId、policy表单域的情况下,必须提供Signature表单域。

  • 该表单域的Key大小写不敏感,但表单域的Value值大小写敏感。

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

Conditions匹配方式

Conditions匹配方式

描述

content-length-range

指定所允许上传的文件最大和最小范围,例如允许的文件大小为1~10字节,则可以写为["content-length-range", 1, 10]。

eq

表单域的值必须精确匹配Conditions中声明的值。例如指定key表单域的值必须为a:{"key": "a"} ,则可以写为["eq", "$key", "a"]。

starts-with

表单域的值必须以指定前缀开始。例如,如果要指定key的值以user/user1开始,则可以写为["starts-with", "$key", "user/user1"]。

in

以字符串列表的形式指定需包含的检查元素。例如通过PostObject接口上传图片时,需校验上传的文件为图片类型,但允许多种格式的图片,则通过in语义指定为["in", "$content-type", ["image/jpg", "image/png"]]。

not-in

以字符串列表的形式指定需排除的检查元素。例如通过PostObject接口上传时需要指定Object缓存行为,且不支持no-cache的形式,则通过not-in语义指定为["not-in", "$cache-control", ["no-cache"]]。

policy转义字符

在Post policy中$表示变量。如果要描述$,需要使用转义字符\$。下表描述了在Post policy的JSON中需要进行转义的字符。

转义字符

描述

\/

斜杠

\\

反斜杠

\”

双引号

\$

美元符

\b

空格

\f

换页

\n

换行

\r

回车

\t

水平制表符

\uxxxx

Unicode字符

签名计算过程

  1. 创建utf-8编码的policy。

  2. 构造StringToSign。

    将policy进行Base64编码,生成一个安全传输的字符串,作为待签名字符串(StringToSign)。

  3. 计算Signature。

    使用AccessKeySecret对要签名的字符串进行签名,签名方法为Signature = base64(hmac-sha1(AccessKeySecret,base64(policy)))

image

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=