To ensure the validity and security of a PostObject request, you must include a signature in the PostObject request. The V4 signature in the PostObject request is calculated by encrypting a series of request parameters, including policy and expiration, based on the AccessKey secret, the current time, and the region. After the application server generates a signature, the application server returns information including the signature and upload policy to the client. The client uses the information to create an upload request. After OSS receives the upload request, OSS verifies the validity of the signature. Only requests that include a valid signature are allowed. Requests that fail the signature verification are denied.
Signature in a PostObject request
To enhance data security, the PostObject request integrates the V4 signature algorithm. The form elements and policy form field play a key role in ensuring the validity and security of PostObject requests.
Form elements
A form is a collection of fields that are actually carried in a PostObject request to pass information about the object that you want to upload and its metadata. The following table describes the unique form elements of a V4 signature in a PostObject request. For more information about the common form elements, see Form elements.
Element | Type | Required | Description |
x-oss-signature-version | String | Yes | The signature version and the algorithm used to calculate the signature. Set the value to OSS4-HMAC-SHA256. |
x-oss-credential | String | Yes | The credentials that you can use to calculate the signature. Format:
|
x-oss-date | String | Yes | The time when the request was initiated. The time must follow the ISO 8601 standard. Example:
|
x-oss-signature | String | Yes | The description used for signature verification. The value is calculated by encrypting the Base64-encoded policy string by using HMAC-SHA256, and then converting the binary hash obtained by using HMAC-SHA256 into hexadecimal format. |
policy
The policy form field in a PostObject request is used to specify the expiration time and conditions of the PostObject request that you initiate to upload an object by using an HTML form. The value of the policy form field is a JSON string that restricts a PostObject request by specifying multiple parameters, such as the bucket name to which you want to upload the object, the prefix in the object name, the validity period of the request, the allowed HTTP methods, and the object size and content.
The policy form field must contain the expiration and conditions parameters. The following field for the Conditions parameter contains optional parameters, such as the x-oss-security-token parameter, which is only required when you use a security token to construct a signature in the PostObject request. The x-oss-security-token parameter is not required when you use AccessKey pairs to construct signatures in PostObject requests.
{
"expiration": "2023-12-03T13:00:00.000Z",
"conditions": [
{"bucket": "examplebucket"},
{"x-oss-signature-version": "OSS4-HMAC-SHA256"},
{"x-oss-credential": "AKIDEXAMPLE/20231203/cn-hangzhou/oss/aliyun_v4_request"},
{"x-oss-security-token": "CAIS******"},
{"x-oss-date": "20231203T121212Z"},
["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"]]
]
}
Required parameters in the policy form field
expiration
The expiration parameter specifies the expiration time of the request. The time must follow the ISO 8601 standard and must be in GMT. For example,
2023-12-03T13:00:00.000Z
specifies that the PostObject request must be sent before 13:00 on December 3, 2023.conditions
The conditions parameter is a list that specifies the valid values of the form fields in the PostObject request.
Parameter
Type
Required
Description
Matching mode
bucket
String
No
The name of the bucket.
bucket
x-oss-signature-version
String
Yes
The signature version and the algorithm used to calculate the signature. Set the value to OSS4-HMAC-SHA256.
x-oss-signature-version
x-oss-credential
String
Yes
The credentials that you can use to calculate the signature. Format:
<AccessKeyId>/<date>/<region>/oss/aliyun_v4_request
AccessKeyId: the AccessKey ID of the AccessKey pair.
date: the date when the request was initiated.
region: the ID of the Alibaba Cloud region in which the bucket you want to access is located. Example: cn-hangzhou.
oss: the name of the requested service. Set the value to oss.
aliyun_v4_request: the description of the signature version in the request. Set the value to aliyun_v4_request.
x-oss-credential
x-oss-security-token
String
No
This parameter is required only when you use a security token to construct a signature in the PostObject request. You can call the AssumeRole operation of STS to obtain a security token.
x-oss-security-token
x-oss-date
String
Yes
The time when the request was initiated. The time must follow the ISO 8601 standard. Example:
20231203T121212Z
.An offset of up to 15 minutes after the request was initiated is allowed. Therefore, the time when the server receives the request can be up to 15 minutes later than the time specified by
x-oss-date
. This ensures that the requests can be processed as expected even if network transmission latency or time difference between the client and the server exists.The request has a validity period of up to seven days. Seven days after the time specified by
x-oss-date
, OSS denies the request and an error is reported. This ensures the timeliness and security of requests and prevents malicious submission of expired or signed requests.The time specified by
x-oss-date
is used as the timestamp for the string to sign. The value must be the same as that of the date field in the derived keys and that of the x-oss-date field in the policy form field.
x-oss-date
content-length-range
String
No
The allowed minimum and maximum sizes of the object that you want to upload. Unit: bytes.
content-length-range
success_action_status
String
No
The HTTP status code that is returned after the object is uploaded.
eq, starts-with, in, and not-in
key
String
No
The name of the object that you want to upload.
eq, starts-with, in, and not-in
content-type
String
No
The type of the object that you want to upload.
eq, starts-with, in, and not-in
cache-control
String
No
The caching behavior of the object.
eq, starts-with, in, and not-in
Signature calculation process
Create a UTF-8 encoded policy.
Create a string to sign.
Base64-encode the policy to generate a string that can be transmitted securely as the string to sign.
Calculate the signing key.
Encrypt the string to sign by using HMAC-SHA256. Use the derived keys of the account as the keys for using HMAC-SHA256.
Calculate the signature.
Convert the binary hash calculated by using HMAC-SHA256 to a hexadecimal string. The obtained hexadecimal string is the signature used to verify the integrity and validity of the request.
Examples
The following sample code provides an example on how to use the preceding policy to calculate a V4 signature for a PostObject request by using OSS SDK for Java:
import com.aliyun.oss.common.utils.BinaryUtil;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class Demo {
public static void main(String[] args) throws Exception {
// Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
String accesskeyid = System.getenv().get("OSS_ACCESS_KEY_ID");
String accesskeysecret = System.getenv().get("OSS_ACCESS_KEY_SECRET");
// Step 1: Create a policy.
String policy = "{\n" +
" \"expiration\": \"2023-12-03T13:00:00.000Z\",\n" +
" \"conditions\": [\n" +
" {\"bucket\": \"examplebucket\"},\n" +
" {\"x-oss-signature-version\": \"OSS4-HMAC-SHA256\"},\n" +
" {\"x-oss-credential\": \""+accesskeyid+"/20231203/cn-hangzhou/oss/aliyun_v4_request\"},\n" +
" {\"x-oss-date\": \"20231203T121212Z\"},\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" +
"}";
// Step 2: Create a string to sign.
String stringToSign = new String(Base64.encodeBase64(policy.getBytes()));
// Step 3: Calculate the derived keys.
byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), "20231203");
byte[] dateRegionKey = hmacsha256(dateKey, "cn-hangzhou");
byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss");
byte[] signingKey = hmacsha256(dateRegionServiceKey, "aliyun_v4_request");
// Step 4: Calculate the signature.
byte[] result = hmacsha256(signingKey, stringToSign);
String signature = BinaryUtil.toHex(result);
System.out.println("signature:" + signature);
}
public static byte[] hmacsha256(byte[] key, String data) {
try {
// Initialize the HMAC key specification, set the algorithm to HMAC-SHA256, and use the provided key.
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");
// Obtain a Mac instance and use the getInstance method to set the algorithm to HMAC-SHA256.
Mac mac = Mac.getInstance("HmacSHA256");
// Use the key to initialize the Mac instance.
mac.init(secretKeySpec);
// Calculate the HMAC value. Use the doFinal method to receive the data to be calculated and return the calculation results in arrays.
byte[] hmacBytes = mac.doFinal(data.getBytes());
return hmacBytes;
} catch (Exception e) {
throw new RuntimeException("Failed to calculate HMAC-SHA256", e);
}
}
}
Sample output:
signature:1fd071f7ac52de95b2b131cd070974876c3c4fce20cce3802531bdbee13df8b1