You can include the Authorization
header in the HTTP request to carry signature information to indicate that the request
has been authorized.
SDK implementation
SDK | Signature implementation |
---|---|
Java SDK | OSSRequestSigner.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
Authorization = "OSS " + AccessKeyId + ":" + Signature
Signature = base64(hmac-sha1(AccessKeySecret,
VERB + "\n"
+ Content-MD5 + "\n"
+ Content-Type + "\n"
+ Date + "\n"
+ CanonicalizedOSSHeaders
+ CanonicalizedResource))
Detail analysis:
AccessKeySecret
specifies the key required for a signature.VERB
specifies the HTTP request method such as PUT, GET, POST, HEAD, and DELETE.\n
specifies a line break.Content-MD5
specifies the MD5 value of the request. The MD5 value is obtained by calculating the message content (excluding the header) and then encoding the resulting 128-bit number in Base64. This header can be used to check the validity of a message. It provides a checking mechanism for whether the message content is consistent with the sent content, such as "eB5eJF1ptWaXm4bijSPyxw==". This header may be left empty. For more information, visit RFC 2616 Content-MD5.Content-Type
specifies the type of the request content, such as application/octet-stream. This header may be left empty.Date
specifies the operation time in GMT format, such as Sun, 22 Nov 2015 08:16:38 GMT.CanonicalizedOSSHeaders
specifies an assembly of HTTP headers that are sorted in alphabetical order and whose prefixes are x-oss-.CanonicalizedResource
specifies the OSS resources you want to access.
Construct CanonicalizedOSSHeaders
All the HTTP headers whose prefixes are x-oss- are called CanonicalizedOSSHeaders. You can construct CanonicalizedOSSHeaders as follows:
- Convert the names of all HTTP request headers whose prefixes are x-oss- into lowercase
letters. For example, convert
X-OSS-Meta-Name: TaoBao
intox-oss-meta-name: TaoBao
. - If the request is sent by using the AccessKey ID and AccessKey secret obtained by
STS, you must add the obtained security-token value to the signature string in
x-oss-security-token:security-token
format. - Sort all the obtained HTTP request headers in alphabetical order.
- Delete any spaces on either end of the delimiter between the header and content of
each request. For example, convert
x-oss-meta-name: TaoBao
intox-oss-meta-name:TaoBao
. - Separate the header and content of each request with the
\n
delimiter to form the final CanonicalizedOSSHeaders.
- CanonicalizedOSSHeaders can be left empty, and the
\n
delimiter at the end can be removed. - To construct only one CanonicalizedOSSHeaders, you must add the
\n
delimiter to the end of the header. Example:x-oss-meta-a\n
. - To construct multiple CanonicalizedOSSHeaders, you must add the
\n
delimiter to the end of each header. Example:x-oss-meta-a:a\nx-oss-meta-b:b\nx-oss-meta-c:c\n
.
Construct CanonicalizedResource
The target OSS resource specified in the request sent by the user is called a CanonicalizedResource. You can construct a CanonicalizedResource as follows:
- Set CanonicalizedResource to a null character string
""
. - Specify the OSS resource you want to access in the following format:
/BucketName/ObjectName
. If ObjectName does not exist, CanonicalizedResource is /BucketName/. If BucketName does not exist either, CanonicalizedResource is a forward slash (/). - If the requested resource includes subresources (SubResource), sort all subresources
in alphabetical order and separate the subresources with the ampersand (
&
) delimiter to generate a subresource string. Add a question mark (?
) and the subresource string to the end of the CanonicalizedResource string. In this case, CanonicalizedResource is/BucketName/ObjectName?acl&uploadId=UploadId
.
- The subresources supported by OSS currently include: 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.
- Three types of subresources are available:
- Resource identifiers such as acl, append, uploadId, and symlink subresources. For more information, see Bucket operations and Object operations.
- Subresources that specify the response header fields, such as
response-***
subresources. For more information, see theRequest parameters
section in GetObject. - Object processing methods such as
x-oss-process
. For more information, see Image Processing.
Rules to calculate a signature header
- A signature string must be in
UTF-8
format. 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 defined in RFC 2104 is used to calculate the final signature. In this method, the Key is AccessKeySecret.
Content-Type
andContent-MD5
are not required in a request. If the request requires signature verification, null values must be replaced with a line break (\n
).- Among non-HTTP headers, only the headers starting with
x-oss-
require signature strings. Other non-HTTP headers are ignored by OSS. For example, the x-oss-magic header in the following example must include a signature string.Note Headers starting withx-oss-
must comply with the following specifications before signature verification:- The header name is converted to lowercase letters.
- The headers are 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 break (\n). If no header is used, set CanonicalizedOSSHeaders to null.
Examples
Request | Signature string calculation formula | Signature string |
---|---|---|
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: foo@bar.com 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:foo@bar.com\n/oss-example/nels |
If AccessKeyId is "44CF959******252F707" and AccessKeySecret is "OtxrzxIsfpFjA7Sw******8Bw21TLhquhboDYROV", you can use the following method to calculate the signature in Python:
import base64
import hmac
import sha
h = hmac.new("OtxrzxIsfpFjA7Sw******8Bw21TLhquhboDYROV",
"PUT\nODBGOERFMDMzQTczRUY3NUE3NzA5QzdFNUYzMDQxNEM=\ntext/html\nThu, 17 Nov 2005 18:49:58 GMT\nx-oss-magic:abracadabra\nx-oss-meta-author:foo@bar.com\n/oss-example/nelson", sha)
Signature = base64.b64encode(h.digest())
print("Signature: %s" % Signature)
The signature calculation result is 26NBxoKd******Dv6inkoDft/yA=. Based on the formula Authorization = "OSS" + AccessKeyId + ":" + Signature, the value of Authorization is OSS 44CF95900***BF252F707:26NBxoKd******Dv6inkoDft/yA=. The value is added with the Authorization header to form the message to be sent:
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: foo@bar.com
X-OSS-Magic: abracadabra
Detail analysis:
- If the entered AccessKey ID does not exist or is not activated, 403 Forbidden is returned. Error code: InvalidAccessKeyId.
- If the value of the Authorization header in the request is in an invalid format, 400 Bad Request is returned. Error code: InvalidArgument.
- All OSS requests must use the GMT time format provided in HTTP 1.1. The format is
as follows:
date1 = 2DIGIT SP month SP 4DIGIT; day month year (e.g., 02 Jun 1982).
Note In this format, day is in 2-digit form. Therefore, "Jun 2", "2 Jun 1982", and "2-Jun-1982" are all invalid formats. - If no date is entered or the date is in the invalid format during signature verification, 403 Forbidden is returned. Error code: AccessDenied.
- The request must be entered within 15 minutes after the current time of the OSS server. Otherwise, 403 Forbidden is returned. Error code: RequestTimeTooSkewed.
- If the AccessKey ID is activated but OSS determines that the signature of the user
request is incorrect, 403 Forbidden is returned. The correct signature string for
verification and encryption is returned to the user in the response message. You can
check whether the signature string is correct based on the response of OSS.
Sample responses:
<? 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>
Calculate the Content-MD5 value
The message content "123456789" is used as an example. The following section provides a detailed description about the correct and incorrect methods to calculate the Content-MD5 value of the string.
- Correct method
- Calculate the MD5-encrypted 128-bit binary array.
- Encode the binary array (instead of the 32-bit string) in Base64.
The following code provides an example on how to calculate the Content-MD5 value in Python:>>> import base64,hashlib >>> hash = hashlib.md5() >>> hash.update("0123456789") >>> base64.b64encode(hash.digest()) 'eB5eJF1ptWaXm4bijSPyxw=='
Call the hash.digest() function to obtain a 128-bit binary array.
>>> hash.digest() 'x\x1e^$]i\xb5f\x97\x9b\x86\xe2\x8d#\xf2\xc7'
- Incorrect method
Note A common incorrect method is to directly encode the 32-bit string in Base64.
# Call the hash.hexdigest() function to obtain a visible 32-bit string. >>> hash.hexdigest() '781e5e245d69b566979b86e28d23f2c7' # Result of encoding the MD5 value in Base64: >>> base64.b64encode(hash.hexdigest()) 'NzgxZTVlMjQ1ZDY5YjU2Njk3OWI4NmUyOGQyM2YyYzc='