All Products
Search
Document Center

Object Storage Service:POST V1 signature

Last Updated:Mar 20, 2026

POST V1 signature authenticates browser-based and direct uploads to OSS using the PostObject operation. The application server signs a policy document with the AccessKey secret and sends the resulting signature and policy to the client. The client attaches both to the multipart form upload. OSS validates the signature on receipt and rejects any request that fails authentication.

Important

OSS supports the more secure V4 signature algorithm. Use V4 signature for new integrations.

How it works

  1. The application server creates a JSON policy that defines upload constraints (bucket, allowed object prefixes, file size limits, expiration time).

  2. The server Base64-encodes the policy to produce the StringToSign, then signs it with HMAC-SHA1 using the AccessKey secret.

  3. The server returns the policy, signature, and AccessKeyId to the client.

  4. The client includes all three in the multipart/form-data POST request to OSS.

  5. OSS validates the signature and enforces the policy conditions before accepting the upload.

Form fields

A POST upload request carries the file and its metadata as HTML form fields. The following fields are specific to the V1 signature scheme. For all other supported form fields, see PostObject form elements.

FieldTypeRequiredDescription
OSSAccessKeyIdStringRequired for authenticated requestsThe AccessKey ID from your AccessKey pair. Required when the bucket ACL is public-read or private, or when the Signature and policy fields are present.
SignatureStringRequired for authenticated requestsThe HMAC-SHA1 signature calculated from the AccessKey secret and the policy. Required when the bucket ACL is public-read or private, or when OSSAccessKeyId and policy are present. The field name is case-insensitive; the value is case-sensitive.
policyStringRequired for authenticated requestsA JSON document that defines upload permissions and constraints. Must include the expiration and conditions fields.

Policy

The policy is a JSON document that restricts what the client can upload. OSS rejects any upload that does not satisfy the policy 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/jpeg", "image/png"]],
    ["not-in", "$cache-control", ["no-cache"]]
  ]
}

expiration

Specifies when the policy expires, in ISO 8601 GMT format. OSS rejects uploads submitted after this time.

Example: "2023-12-03T13:00:00.000Z" — the upload must start before 13:00 UTC on December 3, 2023.

conditions

An array of constraints that each form field value must satisfy. The following fields are supported:

FieldTypeDescriptionSupported matching modes
bucketStringThe bucket name.bucket
content-length-rangeStringThe minimum and maximum object size in bytes.content-length-range
keyStringThe object name.eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci
success_action_statusStringThe HTTP status code returned after a successful upload.eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci
content-typeStringThe MIME type of the uploaded object.eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci
cache-controlStringThe Cache-Control header value.eq, eq-ci, starts-with, starts-with-ci, in, in-ci, not-in, not-in-ci

Condition matching modes

Each condition entry in the conditions array uses a matching mode to define how OSS evaluates the field value.

Exact match (`eq` and object format)

Two formats are equivalent for exact matching:

{"key": "uploads/photo.jpg"}
["eq", "$key", "uploads/photo.jpg"]

Both require the key field to equal "uploads/photo.jpg" exactly.

ModeDescriptionExample
content-length-rangeRestricts object size to a min–max range in bytes.["content-length-range", 1, 10485760]
eqExact match (case-sensitive).["eq", "$key", "uploads/photo.jpg"]
eq-ciExact match (case-insensitive). For ["eq-ci", "$key", "Photo.jpg"], values photo.jpg, PHOTO.JPG, and Photo.jpg all match.["eq-ci", "$key", "Photo.jpg"]
starts-withPrefix match (case-sensitive).["starts-with", "$key", "user/alice/"]
starts-with-ciPrefix match (case-insensitive). For ["starts-with-ci", "$key", "User/"], values starting with user/, USER/, or User/ all match.["starts-with-ci", "$key", "User/"]
inValue must be in a list (case-sensitive).["in", "$content-type", ["image/jpeg", "image/png"]]
in-ciValue must be in a list (case-insensitive).["in-ci", "$content-type", ["IMAGE/JPEG", "image/PNG"]]
not-inValue must not be in a list (case-sensitive).["not-in", "$cache-control", ["no-cache"]]
not-in-ciValue must not be in a list (case-insensitive).["not-in-ci", "$cache-control", ["No-Cache"]]

Policy escape characters

In a policy, $ denotes a variable. To include a literal $, use \$. The following characters must be escaped in the policy JSON:

Escape sequenceCharacter
\/Forward slash
\\Backslash
\"Double quotation mark
\$Dollar sign
\bSpace
\fForm feed
\nLine break
\rCarriage return
\tHorizontal tab
\uxxxxUnicode character

Calculate the signature

The signing process has three steps:

  1. Encode the policy. Encode the policy JSON as UTF-8.

  2. Construct the StringToSign. Base64-encode the UTF-8 policy. The result is the StringToSign.

  3. Sign. Apply HMAC-SHA1 to the StringToSign using the AccessKey secret, then Base64-encode the result.

Signature = base64(hmac-sha1(AccessKeySecret, base64(policy)))
Signature calculation diagram

Example: calculate a POST signature in Java

The following Java example demonstrates the complete signing process for a given policy. Intermediate values are included so you can verify each step of your implementation before using real credentials.

import org.apache.commons.codec.binary.Base64;

public class Demo {
    public static void main(String[] args) {
        // Read the AccessKey secret from an environment variable.
        // Never hard-code credentials in source code.
        String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");

        // Step 1: Define the 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/jpeg\", \"image/png\"]],\n" +
                "    [\"not-in\", \"$cache-control\", [\"no-cache\"]]\n" +
                "  ]\n" +
                "}";

        // Step 2: Base64-encode the policy to produce the StringToSign.
        String stringToSign = new String(Base64.encodeBase64(policy.getBytes()));

        // Step 3: Sign the StringToSign with HMAC-SHA1.
        String signature = com.aliyun.oss.common.auth.ServiceSignature.create()
                .computeSignature(accessKeySecret, stringToSign);

        System.out.println("signature:" + signature);
    }
}

Expected intermediate and final values for the policy above:

StepValue
StringToSign (Base64-encoded policy)ewogICJleHBpcmF0aW9uIjogIjIwMjMtMTItMDNUMTM6MDA6MDAuMDAwWiIsCiAgImNvbmRpdGlvbnMiOiBbCiAgICB7ImJ1Y2tldCI6ICJleGFtcGxlYnVja2V0In0sCiAgICBbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwgMSwgMTBdLAogICAgWyJlcSIsICIkc3VjY2Vzc19hY3Rpb25fc3RhdHVzIiwgIjIwMSJdLAogICAgWyJzdGFydHMtd2l0aCIsICIka2V5IiwgInVzZXIvZXJpYy8iXSwKICAgIFsiaW4iLCAiJGNvbnRlbnQtdHlwZSIsIFsiaW1hZ2UvanBlZyIsICJpbWFnZS9wbmciXV0sCiAgICBbIm5vdC1pbiIsICIkY2FjaGUtY29udHJvbCIsIFsibm8tY2FjaGUiXV0KICBdCn0=
SignaturehR2cJnoG9uzrZLDAmrfOtUjtkSM=
The StringToSign value above is the Base64 encoding of the exact policy string in the example. If your policy uses different whitespace or field ordering, your StringToSign will differ. Compute the signature against your own StringToSign and compare the final signature to verify your implementation.

What's next

  • PostObject — full API reference for the PostObject operation, including all supported form fields

  • V4 signature — the recommended signature algorithm for new integrations