This example shows how to manually construct an Authorization header and upload an object to OSS using the PutObject API in Python 2.7, without relying on the OSS SDK's built-in signing.
For production use, use the OSS SDK, which handles request signing automatically. Use this example only when you cannot use the SDK — for example, when integrating OSS into a custom HTTP stack or debugging authentication flows.
Prerequisites
Before you begin, ensure that you have:
An Alibaba Cloud account with an AccessKey ID and AccessKey secret
An OSS bucket in the
oss-cn-hangzhouregion (or update the endpoint to match your bucket's region)A local file to upload
Python 2.7 with the standard library available (
hmac,base64,urllib2)
How it works
A signed PutObject request requires three headers:
| Header | Description |
|---|---|
Authorization | Authenticates the request. Format: OSS <AccessKeyID>:<Base64(HMAC-SHA1(StringToSign))> |
Content-Type | The MIME type of the object being uploaded (for example, image/png) |
Date | The current UTC time in GMT format, matching the time used when computing the signature |
Authorization header format
The Authorization header has this structure:
OSS <AccessKeyID>:<Signature>| Component | Description |
|---|---|
OSS | Fixed prefix that identifies the Alibaba Cloud OSS signing scheme |
<AccessKeyID> | Your AccessKey ID |
: | Delimiter between the AccessKey ID and the signature |
<Signature> | A Base64-encoded HMAC-SHA1 hash of the string-to-sign |
String-to-sign format
The string-to-sign is constructed as:
PUT\n
\n
<Content-Type>\n
<Date>\n
/<bucket>/<object>Where each \n is a literal newline character.
Upload an object with a signed request
The following Python 2.7 code constructs the signature and uploads an object using the PutObject API.
Replace the placeholder values before running:
| Placeholder | Description | Example |
|---|---|---|
Your accesskey | Your AccessKey ID | LTAI5tXxxx |
Your AccesskeySecret | Your AccessKey secret | xXxXxXx |
Your bucket name | The name of your OSS bucket | examplebucket |
/Users/wanghe/Documents/20190717101549.png | The local path of the file to upload | /path/to/your/file.png |
# -*- coding: utf-8 -*-
import base64
import hmac
import sha
import urllib2
from datetime import datetime
accesskey='Your accesskey';
accesskeysecret='Your AccesskeySecret
endpoint='oss-cn-hangzhou.aliyuncs.com'
bucket='Your bucket name'
# The path of the object you want to upload.
object='mytest/test.png'
GMT_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
time = datetime.utcnow().strftime(GMT_FORMAT)
print(time)
signature = hmac.new(accesskeysecret,
"PUT\n\nimage/png\n"+time+"\n"+"/"+bucket+"/"+object,sha)
Signature = base64.b64encode(signature.digest())
print("Signature: %s" % Signature)
opener = urllib2.build_opener(urllib2.HTTPHandler)
with open("/Users/wanghe/Documents/20190717101549.png") as f:
data=f.read()
request = urllib2.Request("http://"+bucket+"."+endpoint+"/"+object, data=data)
request.add_header("Authorization", "OSS "+accesskey+":"+Signature)
request.add_header("Content-Type", "image/png")
request.add_header("Date", time)
request.get_method = lambda:"PUT"
url = opener.open(request)Troubleshooting
If the signature is incorrect, OSS returns a 403 SignatureDoesNotMatch error. Common causes include:
The
Datevalue used to compute the signature does not match theDateheader sent in the requestThe string-to-sign does not use literal newline characters between each field
The
Content-Typevalue in the string-to-sign does not match theContent-Typeheader in the request
What's next
Add signatures to headers — full reference for the OSS signature algorithm