将PUT请求签名到s3 [英] Sign PUT request to s3
问题描述
我正在尝试使用 curl 进行呼叫,以在s3(eu-central-1)中上传文件,而无需使用aswcli(这是必需条件)或boto3进行上传.
I am trying to do a call with curl to upload a file in s3 (eu-central-1) without using aswcli (this is a requirement) or boto3 for uploading.
我正在使用python和botocore的一些方法对请求进行签名,如下所示:
I am using python and some methods from botocore to sign the request as follow:
import datetime
from botocore.credentials import Credentials
from botocore.handlers import calculate_md5
from botocore.awsrequest import AWSRequest
from botocore.auth import S3SigV4Auth
if __name__ == "__main__":
access_key = '<ACCESS>'
secret_key = '<SECRET>'
bucket = 'mybucket'
region = 'eu-central-1'
host = 's3.eu-central-1.amazonaws.com'
SIGV4_TIMESTAMP = '%Y%m%dT%H%M%SZ'
datetime_now = datetime.datetime.utcnow()
xamzdate = datetime_now.strftime(SIGV4_TIMESTAMP)
auth_time = xamzdate[0:8]
filename = 'img.jpg'
f = open(filename, 'rb')
body = f.read()
req = {
'body': body,
'headers': {}
}
calculate_md5(req)
contentMd5 = req['headers']['Content-MD5']
url = 'https://{host}/{bucket}'.format(host=host, bucket=bucket)
params = {'encoding-type': 'url'}
headers = {
'Content-MD5': contentMd5,
'X-Amz-Date': xamzdate, # '20170529T120930Z'
'X-Amz-Content-SHA256': 'UNSIGNED-PAYLOAD',
'X-Amz-Acl': 'public-read',
}
request = AWSRequest('PUT', url, data=body, params=params, headers=headers)
credentials = Credentials(secret_key=secret_key, access_key=access_key)
signer = S3SigV4Auth(credentials=credentials, service_name='s3', region_name=region)
signer.add_auth(request)
signature = request.headers['X-Amz-Content-SHA256']
auth = 'AWS4-HMAC-SHA256 Credential={access_key}/{auth_time}/eu-central-1/s3/aws4_request, ' \
'SignedHeaders=content-md5;host;x-amz-acl;x-amz-content-sha256;x-amz-date, ' \
'Signature={signature}'.format(access_key=access_key,
auth_time=auth_time,
signature=signature,)
print """
curl -X PUT -T "{filename}" \
-H "X-Amz-Date: {xamzdate}" \
-H "Content-MD5: {contentMd5}" \
-H "X-Amz-Content-SHA256: UNSIGNED-PAYLOAD" \
-H "X-Amz-Acl: public-read" \
-H "Authorization: {auth}" \
https://{host}/{bucket}/{filename}
""".format(host=host, bucket=bucket, xamzdate=xamzdate, contentMd5=contentMd5,
filename=filename, auth=auth)
此python代码的输出为
The output of this python code is
curl -X PUT -T "img.jpg" -H "X-Amz-Date: 20170529T143549Z" -H "Content-MD5: 9WXctE9k50XC/AKwC6yYwQ==" -H "X-Amz-Content-SHA256: UNSIGNED-PAYLOAD" -H "X-Amz-Acl: public-read" -H "Authorization: AWS4-HMAC-SHA256 Credential=<ACCESS_KEY>/20170529/eu-central-1/s3/aws4_request, SignedHeaders=content-md5;host;x-amz-acl;x-amz-content-sha256;x-amz-date, Signature=a54ad95ede0d2ff18272bbded9e1940e71065082056ba7a76c38b45beda1b763" https://s3.eu-central-1.amazonaws.com/MYBUCKET/img.jpg
我将Credential =中的access_key替换为url中的存储桶名称. 该命令的结果是:
I replaced the access_key in Credential= and the bucket name in the url. The result of this command is:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<AWSAccessKeyId>MY ACCESS KEY</AWSAccessKeyId>
<StringToSign>AWS4-HMAC-SHA256
20170529T143549Z
20170529/eu-central-1/s3/aws4_request
8901111961918762ddf496956f95d8ea9bcdb2345dee53ef8c0fb0ec49644464
</StringToSign>
<SignatureProvided>a54ad95ede0d2ff18272bbded9e1940e71065082056ba7a76c38b45beda1b763</SignatureProvided>
<StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 31 37 30 35 32 39 54 31 34 33 35...</StringToSignBytes>
<CanonicalRequest>PUT
/mybucket/img.jpg
content-md5:9WXctE9k50XC/AKwC6yYwQ==
host:s3.eu-central-1.amazonaws.com
x-amz-acl:public-read
x-amz-content-sha256:UNSIGNED-PAYLOAD
x-amz-date:20170529T143549Z
content-md5;host;x-amz-acl;x-amz-content-sha256;x-amz-date
UNSIGNED-PAYLOAD
</CanonicalRequest>
<CanonicalRequestBytes>50 55 54 0a 2f 72 7a 76 65 75 63 65 6e 74 72 61 6c 31 2f 69 6d 67...</CanonicalRequestBytes>
<RequestId>BC854A452F8F92A5</RequestId>
<HostId>vDY8VPIO2n/DoTagpEaUANekON0gpWPQrWfVY2QQ09srXRkgX/O3fvgyT2fNdYhiBXQrgs4yoC4=</HostId>
</Error>
似乎我错过了一些东西.有没有人向s3签署放权请求的可行示例?
It seems I miss something. Has anybody a working example of signing a put request to s3?
推荐答案
I figure out meanwhile how to write an asynchronous client for S3 and I published a blog post and the code on github.
这篇关于将PUT请求签名到s3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!