问题描述
通过
Header或者
URL自签名计算
Signature
时,经常会遇到签名计算失败,报错类似如下。
The request signature we calculated does not match the signature you provided.
问题原因
自签名使用有误。
解决方案
此处介绍如何使用PutObjectAPI签名并上传Object资源,请参考并尝试重新自签名。
PutObjectAPI使用说明
执行如下命令,查看PutObject.py工具的使用帮助。
python PutObject.py -h
系统显示类似如下。
Usage: PutObject.py [options]
Options:
-h, --help 展示帮助文档
-i AK 客户控制台上云账号或者RAM子账号的Accesskey,必选项
-k SK 客户控制台上云账号或者RAM子账号的AccessKeySecrety,必选项
-e ED OSS Endpoint地址,OSS控制台概述上可以看到,必选项
-b BK OSS Bucket名称,必选项
-o OBJECTS 上传到OSS的Object名称,必选项
-f FI 读取本地文件的路经,必选项
参考如下命令,通过PutObject.py工具上传资源文件。
python PutObject.py -i Access_Key_XXX -k Access_Key_Secret_XXX -e oss-cn-shanghai.aliyuncs.com -b yourBucket -f localfile.txt -o aliyun.txt
请求头
PUT /yuntest HTTP/1.1
Accept-Encoding: identity
Content-Length: 147
Connection: close
User-Agent: Python-urllib/2.7
Date: Sat, 22 Sep 2018 04:36:52 GMT
Host: yourBucket.oss-cn-shanghai.aliyuncs.com
Content-Type: application/x-www-form-urlencoded
Authorization: OSS Access_Key_XXX:Access_Key_Secret_XXX
响应头
HTTP/1.1 200 OK
Server: AliyunOSS
Date: Sat, 22 Sep 2018 04:36:52 GMT
Content-Length: 0
Connection: close
x-oss-request-id: 5BA5C6E4059A3C2F
ETag: "D0CAA153941AAA1CBDA38AF"
x-oss-hash-crc64ecma: 8478734191999037841
Content-MD5: 0MqhU5QbIp3Ujqqhy9o4rw==
x-oss-server-time: 15
注意事项
- Signature中所有加入计算的参数都要放在Header中,保持Header和Signature一致。
- PUT上传时,Signature计算的Content-Type必须是application/x-www-form-urlencoded。
- 通过Header方式进行签名认证时无法设置过期时间。目前只有SDK、URL签名支持设置过期时间。
更多信息
如下为PutObject.py工具的源码。
#! /us/bin/envy python
#Author: handle
#Update: 2018-09-29
from optparse import OptionParser
import urllib, urllib2
import datetime
import base64
import hmac
import sha
import os
import sys
import time
class Main():
# Initial input parse
def __init__(self,options):
self.ak = options.ak
self.sk = options.sk
self.ed = options.ed
self.bk = options.bk
self.fi = options.fi
self.oj = options.objects
self.left = '\033[1;31;40m'
self.right = '\033[0m'
self.types = "application/x-www-form-urlencoded"
self.url = 'http://{0}.{1}/{2}'.format(self.bk,self.ed,self.oj)
# Check client input parse
def CheckParse(self):
if (self.ak and self.sk and self.ed and self.bk and self.oj and self.fi) != None:
if str(self.ak and self.sk and self.ed and self.bk and self.oj and self.fi):
self.PutObject()
else:
self.ConsoleLog("error","Input parameters cannot be empty")
# GET local GMT time
def GetGMT(self):
SRM = datetime.datetime.utcnow()
GMT = SRM.strftime('%a, %d %b %Y %H:%M:%S GMT')
return GMT
# GET Signature
def GetSignature(self):
mac = hmac.new("{0}".format(self.sk),"PUT\n\n{0}\n{1}\n/{2}/{3}".format(self.types,self.GetGMT(),self.bk,self.oj), sha)
Signature = base64.b64encode(mac.digest())
return Signature
# PutObject
def PutObject(self):
try:
with open(self.fi) as fd:
files = fd.read()
except Exception as e:
self.ConsoleLog("error",e)
try:
request = urllib2.Request(self.url, files)
request.add_header('Host','{0}.{1}'.format(self.bk,self.ed))
request.add_header('Date','{0}'.format(self.GetGMT()))
request.add_header('Authorization','OSS {0}:{1}'.format(self.ak,self.GetSignature()))
request.get_method = lambda:'PUT'
response = urllib2.urlopen(request,timeout=10)
fd.close()
self.ConsoleLog(response.code,response.headers)
except Exception,e:
self.ConsoleLog("error",e)
# output error log
def ConsoleLog(self,level=None,mess=None):
if level == "error":
sys.exit('{0}[ERROR:]{1}{2}'.format(self.left,self.right,mess))
else:
sys.exit('\nHTTP/1.1 {0} OK\n{1}'.format(level,mess))
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-i",dest="ak",help="Must fill in Accesskey")
parser.add_option("-k",dest="sk",help="Must fill in AccessKeySecrety")
parser.add_option("-e",dest="ed",help="Must fill in endpoint")
parser.add_option("-b",dest="bk",help="Must fill in bucket")
parser.add_option("-o",dest="objects",help="File name uploaded to oss")
parser.add_option("-f",dest="fi",help="Must fill localfile path")
(options, args) = parser.parse_args()
handler = Main(options)
handler.CheckParse()
适用于
如果您的问题仍未解决,您可以在阿里云社区
提交工单联系阿里云技术支持。