我想为我的存储桶中的对象创建一个预先指定的URL。我使用以下python代码:
client = boto3.client(
's3',
aws_access_key_id=os.environ['AWS_ACCESS_KEY'],
aws_secret_access_key=os.environ['AWS_SECRETS_KEY'],
config=botocore.client.Config(signature_version='s3v4'),
region_name='eu-central-1'
)
url = client.generate_presigned_url(
ClientMethod='get_object',
ExpiresIn=60,
Params={
'Bucket': MYBUCKET,
'Key': MYKEY
})
然后我将生成的URL发送到我的前端。在客户端上,我将使用生成的链接创建一个标记,并在其上使用click()方法。这在其他项目中运行良好,但在这里我只得到错误:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
这很奇怪。用户应具有所有必要的权利。因为列出我的存储桶中的所有文件都可以正常工作。
有人能指出我正确的方向,为什么这不起作用?
修改
如果这有帮助的话,我在前端使用next.js。
答案 0 :(得分:1)
问题是boto3的版本。
我尝试了最新版本(boto3 1.7.14),产生了上述错误。
与1.6.6版本完全一样。
答案 1 :(得分:0)
有完全相同的问题。研究了AWS文档并亲自编写了(签名v4)过程。以下基于
https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
并且完美运行。
ENCODING = 'utf8'
SEVEN_DAYS = 604800
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def sign(key, msg):
return hmac.new(key, msg.encode(ENCODING), hashlib.sha256).digest()
def get_signature_key(key, dateStamp, regionName, serviceName):
kDate = sign(('AWS4' + key).encode(ENCODING), dateStamp)
kRegion = sign(kDate, regionName)
kService = sign(kRegion, serviceName)
kSigning = sign(kService, 'aws4_request')
return kSigning
def generate_presigned_s3_get(bucket, object_key, region, expires_in, access_key, secret_key):
METHOD = 'GET'
SERVICE = 's3'
host = bucket + '.s3.' + region + '.amazonaws.com'
endpoint = 'https://' + host
t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')
canonical_uri = '/' + object_key
canonical_headers = 'host:' + host + '\n'
signed_headers = 'host'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + SERVICE + '/' + 'aws4_request'
canonical_querystring = '?X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring += '&X-Amz-Credential=' + urllib.parse.quote_plus(access_key + '/' + credential_scope)
canonical_querystring += '&X-Amz-Date=' + amz_date
canonical_querystring += '&X-Amz-Expires=' + str(expires_in)
canonical_querystring += '&X-Amz-SignedHeaders=' + signed_headers
canonical_request = METHOD + '\n' + canonical_uri + '\n' + canonical_querystring[1:] + '\n' + canonical_headers + '\n' + signed_headers + '\nUNSIGNED-PAYLOAD'
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode(ENCODING)).hexdigest()
signing_key = get_signature_key(secret_key, datestamp, region, SERVICE)
signature = hmac.new(signing_key, (string_to_sign).encode("utf-8"), hashlib.sha256).hexdigest()
canonical_querystring += '&X-Amz-Signature=' + signature
url = endpoint + canonical_uri + canonical_querystring
logger.info('presigned url: %s' % url)
return url
我也向boto3偷窥报告了此问题: https://github.com/boto/boto3/issues/1644