You can include the Authorization
header in an HTTP request to carry signature information and indicate that the requester is authorized.
Sign requests when you use OSS SDKs
SDK | Sample code |
---|---|
Java SDK | SignUtils.java |
Python SDK | auth.py |
.Net SDK | OssRequestSigner.cs |
PHP SDK | OssClient.php |
C SDK | oss_auth.c |
JavaScript SDK | client.js |
Go SDK | auth.go |
Ruby SDK | util.rb |
iOS SDK | OSSModel.m |
Android SDK | OSSUtils.java |
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))
The following table describes the parameters that you can specify in the preceding command.
Parameter | Type | Required | Example | Description |
---|---|---|---|---|
AccessKeyId | String | Yes | LTAI4FixJvEPgvZ6g5cC**** | The AccessKey ID that is used to access OSS. |
AccessKeySecret | String | Yes | Q0YehC6ZyugWfjod5y8Rcqrc1y**** | The AccessKey secret that is used to access OSS. |
VERB | Enumeration | Yes | PUT | The method of the HTTP request, such as PUT, GET, POST, HEAD, DELETE, or OPTIONS. |
\n | String | No | \n | The line feed. |
Content-MD5 | String | No | eB5eJF1ptWaXm4bijSPyxw== | The Content-MD5 value is the MD5 hash of the requested content. The message content that excludes the header is calculated to obtain an MD5 hash, which is a 128-bit number. This number is encoded in Base64 to generate the Content-MD5 value. For more information, see RFC 2616 Content-MD5. The request header can be used to check the validity of a message. The message content is valid if the received message content is the same as the content that is sent. This parameter can be left empty. For more information about how to calculate the Content-MD5 value, see Calculation of Content-MD5. |
Content-Type | String | No | application/octet-stream | The type of the request content. This parameter can be left empty. |
Date | String | Yes | Sun, 22 Nov 2015 08:16:38 GMT | The time when the operation is performed. The value of this parameter must be in UTC. This parameter cannot be left empty. The value of the parameter is calculated from the Date header or x-oss-date header of the request. When the two headers exist at the same time, the x-oss-date takes precedence. Important If the difference between the time that is specified by the Date header in a request and the time on the server when the request is received is greater than 15 minutes, OSS rejects the request and returns the HTTP status code 403. |
CanonicalizedOSSHeaders | String | No | x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n | The HTTP headers that are prefixed with x-oss- . The HTTP headers are sorted in alphabetical order.
For more information about how to construct CanonicalizedOSSHeaders, see Creation of CanonicalizedOSSHeaders. |
CanonicalizedResource | String | Yes | examplebucket | The OSS resource that you want to access. This parameter cannot be left empty. For more information about how to construct CanonicalizedResource, see Creation of CanonicalizedResource. |
Examples
- Example 1 (includes all parameters)
Request Formula Signature string PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== 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 eB5eJF1ptWaXm4bijSPyxw==\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 If the AccessKey ID is LTAI4FixJvEPgvZ6g5cC**** and the AccessKey secret is Q0YehC6ZyugWfjod5y8Rcqrc1y****, you can run the following Python code to calculate the signature:
import hmac import hashlib import base64 h = hmac.new("Q0YehC6ZyugWfjod5y8Rcqrc1y****".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 calculated signature is
J9Nl3b+xdEKNQGWFhhZpjSLm****
. The following example shows the final request that includes the Authorization header:PUT /nelson HTTP/1.0 Authorization:OSS LTAI4FixJvEPgvZ6g5cC****:J9Nl3b+xdEKNQGWFhhZpjSLm**** Content-Md5: eB5eJF1ptWaXm4bijSPyxw== 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 (does not include the optional parameters 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 If the AccessKey ID is LTAI5t7h6SgiLSganP2m**** and the AccessKey secret is KZo149BD9GLPNiDIEmdQ7dyNKG****, you can run the following Python code to calculate the signature:
import hmac import hashlib import base64 h = hmac.new("KZo149BD9GLPNiDIEmdQ7dyNKG****".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 calculated signature is
Mhb1MkIfOlZTnBXZE5Hleb/2****
. The following example shows the final request that includes the Authorization header:PUT /nelson HTTP/1.0 Authorization:OSS LTAI5t7h6SgiLSganP2m****:Mhb1MkIfOlZTnBXZE5Hleb/2**** 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 imported AccessKey ID does not exist or is not activated, 403 Forbidden is returned with the error code InvalidAccessKeyId. If the imported AccessKey ID is activated but OSS determines that a signature error occurs in the request, 403 Forbidden is returned with the correct signature string in the response to verify the encryption. You can check whether the signature string is correct based on the response. 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 format of the Authorization value in the request is invalid, 400 Bad Request is returned with the error code InvalidArgument.
- The date and the time in all OSS requests must be in UTC that is specified in HTTP/1.1, in which the date is in the following format:
date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)
Note In the preceding date format,day
uses two digits. Therefore,Jun 2
,2 Jun 1982
, and2-Jun-1982
are all invalid date formats.- If the Date header is not specified or is in an invalid format in a signed request, 403 Forbidden is returned with the error code AccessDenied.
- If the difference between the time specified by the Date header in a request and the time on the server when the request is received is greater than 15 minutes, 403 Forbidden is returned with the error code RequestTimeTooSkewed.
Creation of CanonicalizedOSSHeaders
All HTTP headers prefixed with x-oss-
are called CanonicalizedOSSHeaders. You can perform the following steps to create CanonicalizedOSSHeaders:
- Convert the names of all HTTP request headers prefixed with
x-oss-
into lowercase letters. For example, convertX-OSS-Meta-Name: TaoBao
intox-oss-meta-name: TaoBao
. - If the request is sent by using a temporary access credential obtained from Security Token Service (STS), you must add the obtained security-token value to the signature string in the
x-oss-security-token:security-token
format.Note For more information about how to configure STS, see Use temporary credentials provided by STS to access OSS. You can call the AssumeRole operation or use STS SDKs for various programming languages to obtain a temporary access credential. Temporary access credentials contain a security token and a temporary AccessKey pair that consists of an AccessKey ID and an AccessKey secret. - Sort all HTTP request headers in alphabetical order.
- Delete all spaces on each side of the delimiter between each header and head value. For example, convert
x-oss-meta-name: TaoBao
intox-oss-meta-name:TaoBao
. - Separate all headers with the
\n
delimiter to create CanonicalizedOSSHeaders.
Creation of CanonicalizedResource
The OSS resources that are required in a request are called CanonicalizedResource. You can perform the following operations to construct CanonicalizedResource:
- If the resource contains a bucket and an object, set CanonicalizedResource to /BucketName/.
- If the resource contains a bucket, set CanonicalizedResource to /BucketName/.
- If the resource does not contain a bucket or an object, set CanonicalizedResource to a forward slash /.
- If the resource contains subresources, sort all subresources in ascending alphabetical order and separate them with ampersands (
&
). Add a question mark (?
) and the subresource string to the end of the CanonicalizedResource string. In this example, the created CanonicalizedResource is in the following 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. Important Resource identifiers are case-sensitive.
- Response header fields, such as response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, and response-content-encoding. For more information, see GetObject.
- IMG implementation modes, such as
x-oss-process
. For more information, see Overview. - Access control fields that start 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. For more information, see Add signatures to URLs.Note After you use CanonicalizedResource that contains x-oss-ac-source-ip to generate a signature, remove x-oss-ac-source-ip from the query parameters in the request to prevent IP address leaks.
- 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.
Rules of the signature calculation
- The signature string used to calculate the signature must be encoded in
UTF-8
. A signature string that contains Chinese characters must be encoded inUTF-8
. The encoded signature string is used together withAccessKeySecret
to calculate the final signature. - The HMAC-SHA1 method that is specified in RFC 2104 is used to calculate the signature. In this method, Key indicates the AccessKey secret.
Content-Type
andContent-MD5
can be left unspecified in a request. However, if OSS needs to verify the signature of the request, the values of these two headers must be replaced with line feeds (\n
).- Non-standard HTTP headers prefixed with
x-oss-
must be added to the signature string. Other non-standard HTTP headers are ignored by OSS. For example, the x-oss-meta-magic header in the following example must be included in the signature string.Note Headers prefixed withx-oss-
in the signature string must comply with the following conventions:- The names of headers must be in lowercase.
- The headers must be sorted in ascending alphabetical order.
- No space exists before or after the colon (:) that separates each header name and value.
- Each header is followed by a line feed (\n). If no header is specified, leave CanonicalizedOSSHeaders empty.
Calculation of Content-MD5
In the following examples, the string "123456789" is used to show how to calculate the Content-MD5 value of the request content.
- Correct calculation
- Calculate the MD5 hash of the string, which is a 128-bit binary array.
- Encode the binary array (instead of the 32-bit string) in Base64.
The following Python code provides an example on how to calculate the Content-MD5 value:>>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") // If you use Python 3, change this part to hash.update(b"0123456789"). >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw=='
Call hash.digest() to calculate the 128-bit binary array.
>>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7'
- Incorrect calculation Note A common incorrect operation is to encode the calculated 32-bit string in Base64 to obtain the Content-MD5 value.
# Call hash.hexdigest() to obtain a 32-bit plaintext string. >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' # The following code provides an example on the result of encoding the incorrect MD5 hash in Base64: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='