All OSS operations except POST and query-parameter-signed requests require the Authorization header, constructed with the V1 (HMAC-SHA1) signature algorithm.
V4 signatures are more secure. Include a V4 signature in the Authorization header (recommended).
Automatic V1 signing with OSS SDKs
OSS SDKs handle V1 signing automatically.
|
SDK |
Sample code |
|
Java |
|
|
PHP |
|
|
Node.js |
|
|
Browser.js |
|
|
Python |
|
|
.NET |
|
|
Android |
|
|
Go |
|
|
iOS |
|
|
C++ |
|
|
C |
|
|
Ruby |
Calculation of the Authorization header
Calculation method
Authorization = "OSS " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
VERB + "\n"
+ Content-MD5 + "\n"
+ Content-Type + "\n"
+ Date + "\n"
+ CanonicalizedOSSHeaders
+ CanonicalizedResource))
Parameters
|
Parameter |
Type |
Required |
Example |
Description |
|
AccessKeyId |
String |
Yes |
LTAI**************** |
AccessKey pair (AccessKey ID and AccessKey secret) for authentication.
|
|
AccessKeySecret |
String |
Yes |
yourAccessKeySecret |
|
|
x-oss-security-token |
String |
No |
CAIS******************************** |
STS security token. Required only for STS-signed requests. For more information about how to obtain a security token, see AssumeRole. |
|
VERB |
Enumeration |
Yes |
PUT |
HTTP request method: PUT, GET, POST, HEAD, DELETE, or OPTIONS. |
|
\n |
String |
No |
\n |
Line feed. |
|
Content-MD5 |
String |
No |
eB5e******************** |
Base64-encoded 128-bit MD5 hash of the request body (excluding headers), per RFC 2616 Content-MD5. Verifies message integrity. For more information about how to calculate the value of Content-MD5, see Calculate Content-MD5. |
|
Content-Type |
String |
No |
application/octet-stream |
MIME type of the request content. Note
If you omit Content-Type during signature calculation, do not include it in the signed request. |
|
Date |
String |
Yes |
Sun, 22 Nov 2015 08:16:38 GMT |
Request timestamp in UTC, from the Date or x-oss-date header. x-oss-date takes precedence. Important
If the Date header differs from the server time by more than 15 minutes, OSS rejects the request with HTTP 403. |
|
CanonicalizedOSSHeaders |
String |
No |
x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n |
HTTP headers prefixed with
For more information about how to construct CanonicalizedOSSHeaders, see the Construct CanonicalizedOSSHeaders section of this topic. |
|
CanonicalizedResource |
String |
Yes |
examplebucket |
The target OSS resource. For more information about how to construct CanonicalizedResource, see the Construct CanonicalizedResource section of this topic. |
Examples
-
Example 1 (all parameters)
Request
Formula
Signature string
PUT /nelson HTTP/1.0 Content-MD5: eB5e******************** Content-Type: text/html Date: Wed, 28 Dec 2022 10:27:41 GMT Host: examplebucket.oss-cn-hangzhou.aliyuncs.com x-oss-meta-author: alice x-oss-meta-magic: abracadabra
Signature = base64(hmac-sha1(AccessKeySecret,VERB + "\n" + Content-MD5 + "\n"+ Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders+ CanonicalizedResource))
PUT\n eB5e********************\n text/html\n Wed, 28 Dec 2022 10:27:41 GMT\n x-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/examplebucket/nelson
Calculate the signature with AccessKey ID LTAI**************** and AccessKey secret yourAccessKeySecret:
import hmac import hashlib import base64 h = hmac.new("yourAccessKeySecret".encode('utf-8'), "PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM\ntext/html\nWed, 28 Dec 2022 10:27:41 GMT\nx-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/oss-example/nelson".encode('utf-8'), hashlib.sha1) signature = base64.encodebytes(h.digest()) print(signature)The signature is
J9Nl3b+xdEKNQGWFhhZpjSLm****. The final request:PUT /nelson HTTP/1.0 Authorization:OSS LTAI****************:J9Nl************************ Content-Md5: eB5e******************** Content-Type: text/html Date: Wed, 28 Dec 2022 10:27:41 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com x-oss-meta-author: alice x-oss-meta-magic: abracadabra -
Example 2 (without Content-MD5 and Content-Type)
Request
Formula
Signature string
PUT /nelson HTTP/1.0 Date: Wed, 28 Dec 2022 09:56:32 GMT Host: examplebucket.oss-cn-hangzhou.aliyuncs.com x-oss-meta-author: alice x-oss-meta-magic: abracadabra
Signature = base64(hmac-sha1(AccessKeySecret,VERB + "\n" + "\n"+ "\n" + Date + "\n" + CanonicalizedOSSHeaders+ CanonicalizedResource))
PUT\n\n\nWed, 28 Dec 2022 09:56:32 GMT\n x-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/examplebucket/nelson
Calculate the signature with AccessKey ID LTAI**************** and AccessKey secret KZo1**************************:
import hmac import hashlib import base64 h = hmac.new("KZo1**************************".encode('utf-8'), "PUT\n\n\nWed, 28 Dec 2022 09:56:32 GMT\nx-oss-meta-magic:abracadabra\nx-oss-meta-author:alice\n/oss-example/nelson".encode('utf-8'), hashlib.sha1) signature = base64.encodebytes(h.digest()) print(signature)The signature is
Mhb1************************. The final request:PUT /nelson HTTP/1.0 Authorization:OSS LTAI****************:Mhb1************************ Date: Wed, 28 Dec 2022 09:56:32 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com x-oss-meta-author: alice x-oss-meta-magic: abracadabra
Additional information
-
If the AccessKey ID does not exist or is inactive, OSS returns 403 Forbidden with InvalidAccessKeyId. If the AccessKey ID is valid but the signature is incorrect, OSS returns 403 Forbidden with the expected signature string for debugging.
Sample response:
<?xml version="1.0" ?> <Error> <Code> SignatureDoesNotMatch </Code> <Message> The request signature we calculated does not match the signature you provided. Check your key and signing method. </Message> <StringToSignBytes> 47 45 54 0a 0a 0a 57 65 64 2c 20 31 31 20 4d 61 79 20 32 30 31 31 20 30 37 3a 35 39 3a 32 35 20 47 4d 54 0a 2f 75 73 72 65 61 6c 74 65 73 74 3f 61 63 6c </StringToSignBytes> <RequestId> 1E446260FF9B**** </RequestId> <HostId> oss-cn-hangzhou.aliyuncs.*** </HostId> <SignatureProvided> y5H7yzPsA/tP4+0tH1HHvPEwUv8= </SignatureProvided> <StringToSign> GET Wed, 11 May 2011 07:59:25 GMT /examplebucket?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VO**** </OSSAccessKeyId> </Error> -
If the Authorization header format is invalid, OSS returns 400 Bad Request with InvalidArgument.
-
OSS request dates must use HTTP/1.1 UTC format:
date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)NoteThe
dayfield requires two digits.Jun 2,2 Jun 1982, and2-Jun-1982are invalid.-
If the Date header is missing or invalid, OSS returns 403 Forbidden with AccessDenied.
-
If the Date header differs from server time by more than 15 minutes, OSS returns 403 Forbidden with RequestTimeTooSkewed.
-
Construct CanonicalizedOSSHeaders
CanonicalizedOSSHeaders includes all HTTP headers prefixed with x-oss-:
-
x-oss--prefixed header names must be lowercased. Example:X-OSS-Meta-Name: TaoBao→x-oss-meta-name: TaoBao. -
For STS temporary credentials, add the security token in the format
x-oss-security-token:security-token.NoteFor more information about how to configure STS, see Access OSS by using STS temporary credentials. You can call the AssumeRole operation or use STS SDKs for various programming languages to obtain temporary access credentials. Temporary credentials consist of a security token and a temporary AccessKey pair.
-
Sort all headers alphabetically by name.
-
Remove spaces around the colon between each header name and value. Example:
x-oss-meta-name: TaoBao→x-oss-meta-name:TaoBao. -
Join all headers with
\nto produce CanonicalizedOSSHeaders.
Construct CanonicalizedResource
CanonicalizedResource identifies the target OSS resource:
-
If the resource contains a bucket and an object, set CanonicalizedResource to /BucketName/ObjectName.
-
If the resource contains a bucket, set CanonicalizedResource to /BucketName/.
-
If the resource does not contain a bucket or an object, set CanonicalizedResource to /.
-
If subresources exist, sort them alphabetically, separate with
&, and append after a?. Format:/BucketName/ObjectName?acl&uploadId=UploadId.OSS supports the following types of subresources:
-
Resource identifiers, such as acl, uploads, location, cors, logging, website, referer, lifecycle, delete, append, tagging, objectMeta, uploadId, partNumber, security-token, position, img, style, styleName, replication, replicationProgress, replicationLocation, cname, bucketInfo, comp, qos, live, status, vod, startTime, endTime, symlink, x-oss-process, callback, and callback-var. For more information, see PutBucket and PutObject.
ImportantResource identifiers are case-sensitive.
-
Response headers, such as response-content-language, response-expires, response-cache-control, response-content-disposition, and response-content-encoding. For more information, see GetObject.
-
Image processing (IMG) modes, such as
x-oss-process. Overview. -
Access control fields starting with
x-oss-ac-*, such as x-oss-ac-source-ip, x-oss-ac-subnet-mask, x-oss-ac-vpc-id, and x-oss-ac-forward-allow. Create a signed URL by using signature V1.NoteAfter generating a signature with x-oss-ac-source-ip, remove x-oss-ac-source-ip from the query parameters to prevent IP address leaks.
-
Signature calculation rules
-
Encode the signature string in
UTF-8. Chinese characters requireUTF-8encoding. Use the encoded string withAccessKeySecretto calculate the signature. -
The signature is calculated using HMAC-SHA1 as defined in RFC 2104, with the AccessKey secret as the key.
-
Content-TypeandContent-MD5are optional. If omitted, substitute line feeds (\n) in the signature string. -
Only headers prefixed with
x-oss-are included in the signature string. OSS ignores other non-standard headers.NoteHeaders prefixed with
x-oss-in the signature string must follow these conventions:-
Header names must be lowercase.
-
Headers must be sorted alphabetically.
-
No spaces before or after the colon separating each header name and value.
-
Each header ends with a line feed (\n). If no headers exist, leave CanonicalizedOSSHeaders empty.
-
Calculate Content-MD5
These examples calculate Content-MD5 for the string "123456789".
-
Correct calculation
-
Calculate the 128-bit MD5 hash of the string.
-
Base64-encode the binary digest (not the 32-character hex string).
Python example:
>>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") // If you use Python 3, change this line to hash.update(b"0123456789"). >>> base64.b64encode(hash.digest()) 'eB5e********************'Call hash.digest() to get the 128-bit binary digest.
>>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7' -
-
Incorrect calculation
NoteA common mistake is Base64-encoding the 32-character hex string instead of the binary digest.
# Call hash.hexdigest() to obtain a 32-bit plaintext string. >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' # The following sample code provides an example of the result of encoding an incorrect MD5 hash in Base64: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='