You can specify the
Authorization header in an HTTP request and include a signature in the value of this header to indicate that the request is authorized.
|OSS SDK for Java||OSSRequestSigner.java|
|OSS SDK for Python||auth.py|
|OSS SDK for .Net||OssRequestSigner.cs|
|OSS SDK for PHP||OssClient.php|
|OSS SDK for C||oss_auth.c|
|OSS SDK for Go||auth.go|
|OSS SDK for Ruby||util.rb|
|OSS SDK for iOS||OSSModel.m|
|OSS SDK for Android||OSSUtils.java|
Calculation of the Authorization header
Authorization = "OSS " + AccessKeyId + ":" + Signature Signature = base64(hmac-sha1(AccessKeySecret, VERB + "\n" + Content-MD5 + "\n" + Content-Type + "\n" + Date + "\n" + CanonicalizedOSSHeaders + CanonicalizedResource))
AccessKeySecretindicates the AccessKey secret used to sign the request.
VERBindicates the method of the request to sign, such as PUT, GET, POST, HEAD, and DELETE.
\nindicates a line feed.
Content-MD5indicates the MD5 hash of the request content. The value of Content-MD5 is a Base64-encoded 128-bit number that is calculated based on the content of the request message excluding request headers. Example: eB5eJF1ptWaXm4bijSPyxw==. This header can be used to check the validity of the request message. When OSS receives a request, OSS determines that the request is valid if the MD5 hash of the request message is the same as that of the request message that is sent. This header can be empty. For more information, visit RFC 2616 Content-MD5.
Content-Typeindicates the type of the request content, such as application/octet-stream. This header can be empty.
Dateindicates the time when this operation is performed, which must be in the GMT format, such as “Sun, 22 Nov 2015 08:16:38 GMT”.
CanonicalizedOSSHeadersindicates an assembly of HTTP headers prefixed with x-oss- in the alphabetical order.
CanonicalizedResourceindicates the OSS resources you want to access.
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, convert
- If the request is sent by using an AccessKey pair obtained from STS, you must add the obtained security-token value to the signature string in the
- Sort all HTTP request headers that are converted in Step 1 in alphabetical order.
- Delete all spaces on each side of the delimiter between each header and its value. For example, convert
- Separate all headers with the
\ndelimiter to create CanonicalizedOSSHeaders.
- CanonicalizedOSSHeaders can be left empty. In this case, the
\ndelimiter at the end can be removed.
- If CanonicalizedOSSHeaders includes only one header, the
\ndelimiter must be added at the end of the header. Example:
- If CanonicalizedOSSHeaders includes multiple headers, the
\ndelimiter must be added at the end of each header. Example:
Creation of CanonicalizedResource
The OSS resources that you send requests to access are called CanonicalizedResource. You can perform the following operations to create CanonicalizedResource:
- Set CanonicalizedResource to an empty string
- Specify the OSS resource you want to access in the following format:
/BucketName/ObjectName. If you want to access a bucket but not a specific object, set CanonicalizedResource in the following format: /BucketName/. If you do not want to specify the resource you want to access, set CanonicalizedResource to a forward slash (/).
- If the resource that you want to access contains subresources, sort all subresources in alphabetical order and separate them with the ampersand (
&) delimiter. 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:
- OSS supports the following subresources: 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, response-content-type, response-content-language, response-expires, response-cache-control, response-content-disposition, and response-content-encoding.
- You can specify the following three types of subresources:
- Resource identifiers such as acl, append, uploadId, and symlink. For more information, see Bucket operations and Object operations.
- Subresources that specify the response header fields, such as
response-***. For more information, see the
Request parameterssection in GetObject.
- Object processing methods such as
x-oss-process. For more information, see Image Processing.
Calculation of the signature
- The signature string used to calculate the signature must be
UTF-8-encoded. A signature string that contains Chinese characters must be encoded in
UTF-8. The encoded string is used together with
AccessKeySecretto calculate the signature.
- The HMAC-SHA1 method defined in RFC 2104 is used to calculate the signature. In this method, the Key is AccessKeySecret.
Content-MD5can 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 by line feeds (
- 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-magic header in the following example must be included in the signature string.Note Headers prefixed with
x-oss-in the signature string must comply with the following conventions:
- The header names must be in lowercase.
- The headers must be sorted in alphabetical order.
- No space exists before or after the colon (:) that separates the header name and value.
- Each header is followed by a line feed (\n). If no header is specified, set CanonicalizedOSSHeaders to null.
|PUT /nelson HTTP/1.0 Content-MD5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: firstname.lastname@example.org X-OSS-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 Thu, 17 Nov 2005 18:49:58 GMT\n x-oss-magic:abracadabra\nx-oss-meta-author:email@example.com\n/oss-example/nelson|
If AccessKeyId is set to "44CF959******252F707" and AccessKeySecret is set to "OtxrzxIsfpFjA7Sw******8Bw21TLhquhboDYROV", you can run the following Python code to calculate the signature:
import hmac import hashlib h = hmac.new(oss2.to_bytes("OtxrzxIsfpFjA7Sw******8Bw21TLhquhboDYROV"), oss2.to_bytes("PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:firstname.lastname@example.org\n/oss-example/nelson"), hashlib.sha1) signature = oss2.utils.b64encode_as_string(h.digest()) print("Signature: %s" % signature)
The calculated signature is 26NBxoKd******Dv6inkoDft/yA=. Therefore, the value of the Authorization header is OSS 44CF95900***BF252F707:26NBxoKd******Dv6inkoDft/yA=, which is in the following format: "OSS"+ AccessKeyId + ":" + Signature. The following example shows the final request that includes the Authorization header:
PUT /nelson HTTP/1.0 Authorization:OSS 44CF95900***BF252F707:26NBxoKd******Dv6inkoDft/yA= Content-Md5: eB5eJF1ptWaXm4bijSPyxw== Content-Type: text/html Date: Thu, 17 Nov 2005 18:49:58 GMT Host: oss-example.oss-cn-hangzhou.aliyuncs.com X-OSS-Meta-Author: email@example.com X-OSS-Magic: abracadabra
- If the specified AccessKey ID does not exist or is not activated, 403 Forbidden is returned with the InvalidAccessKeyId error code.
- If the format of the Authorization header is invalid, 400 Bad Request is returned with the InvalidArgument error code.
- The date and time specified in all OSS requests must be in the GMT format defined in HTTP 1.1, in which date is in the following format:
date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982)Note In the preceding format, the day field is a 2-digit number. Therefore, "Jun 2", "2 Jun 1982", and "2-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 AccessDenied error code.
- 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 RequestTimeTooSkewed error code.
- If the specified AccessKey ID is activated but OSS determines that the signature in a request is incorrect, OSS returns 403 Forbidden and the correct signature string for verification and encryption in the response. You can check whether the signature string is correct based on the 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 /oss-example?acl </StringToSign> <OSSAccessKeyId> AKIAIVAKMSMOY7VO**** </OSSAccessKeyId> </Error>
Calculation of Content-MD5
The following examples use a string "123456789" to show how to calculate the Content-MD5 value of the request content:
- Correct calculation
The following Python code provides an example on how to calculate the Content-MD5 value of the string "123456789":
- 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.
>>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") // If you use Python 3, change the code 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 of encoding the incorrect MD5 hash in Base64: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='