Boto3 generate_presigned_url,SignatureDoesNotMatch错误

时间:2019-09-16 04:59:15

标签: python-3.x amazon-web-services boto3

关于SO和其他地方的一些问题和答案概述了解决从boto3 SDK调用“ generate_presigned_url”时引发的SignatureDoesNotMatch错误的可能解决方案。 boto3中很少有人使用,大多数答案都建议您获取新的凭据来解决此异常。您可以看到更多(但这在PHP中)here

但是这些对我不起作用,因为我使用的是正确的凭据以及正确的存储桶名称和密钥路径。

最初,我打电话给它来生成我的客户端,然后打电话给generate_presigned_url。

client_s3 = boto3.client(
    's3',
    # Hard coded strings as credentials, not recommended.
    aws_access_key_id='XXX',
    aws_secret_access_key='XXX',
    region_name='us-east-2',
    # EDIT: Previously, I used signature_version='v4' here, but as a user here pointed out, this might not work. Regardless, I tried 's3v4' prior to trying 'v4' and neither worked for me.
    config=Config(signature_version='s3v4')
)

url = client_s3.generate_presigned_url(
    ClientMethod='get_object',
    Params={
        'Bucket': 'BUCKET_NAME',
        'Key': 'CORRECT_KEY'
    }
)

当使用的所有参数看似正确时,什么会造成此错误?我该如何解决?

3 个答案:

答案 0 :(得分:2)

documentation of boto3中明确提到该选项应类似于config=Config(signature_version='s3v4')v4不起作用。

这是boto3文档的示例。

import boto3
from botocore.client import Config

# Get the service client with sigv4 configured
s3 = boto3.client('s3', config=Config(signature_version='s3v4'))

# Generate the URL to get 'key-name' from 'bucket-name'
url = s3.generate_presigned_url(
    ClientMethod='get_object',
    Params={
        'Bucket': 'bucket-name',
        'Key': 'key-name'
    }
)

顺便说一句,us-east-2仅允许签名版本4,因此您无需指定它。 See This

答案 1 :(得分:1)

我知道回答有点晚了,但我按照 this GitHub 链接中指定的方法解决了我的问题。

import boto3
import requests

parts = s3_client.generate_presigned_post(Bucket=bucket_name,
                                          Key=key,
                                          Fields={
                                            'acl': 'public-read',
                                            'Content-MD5': str(md5),
                                            'Content-Type': 'binary/octet-stream'
                                            },
                                          Conditions=[
                                              {"acl": "public-read"},
                                              ["starts-with", "$Content-Type", ""],
                                              ["starts-with", "$Content-MD5", ""]
                                          ]
                                      )

url = parts['url']
data = parts['fields']
files = {'file': open(local_path, 'rb')} # the key supposed to be file may be
response = requests.post(url, data=data, files=files)

答案 2 :(得分:0)

看到此AWS forum之后,我发现可能会发生一些麻烦,但是我真的只是想用一个安全的解决方案来解决问题。

我的分辨率绝对不是每个人都最佳,但是对我有用。

我将“ us-east-2”中存储桶中的所有内容复制到“ us-east-1”中的新存储桶中,并且能够使用完全相同的访问/秘密密钥和存储桶/密钥正确访问该存储桶路径。我只是用:

client_s3 = boto3.client(
    's3',
    # Hard coded strings as credentials, not recommended.
    aws_access_key_id='XXX',
    aws_secret_access_key='XXX'
)

如果您像我一样,并且不想花费数小时来尝试破译AWS的不良文档,则可以这样做。如果您有 real 解决方案,请在此处添加。

我仍然不确定是什么原因造成的,但可能与“ v4”签名方法有关,该方法依赖于区域。