boto3签名的url导致SignatureDoesNotMatch

时间:2017-12-12 01:46:50

标签: python amazon-s3 boto3

我的代码已成功将文档上传到正确的存储桶中。我可以登录并查看AWS S3上的文档。当我尝试使用boto3中的generate_signed_url方法获取这些文档的URL然后可以发送给用户访问文档时,我收到一个SignatureDoesNotMatch,其中显示的消息是"我们计算的请求签名与您提供的签名不符。检查您的密钥和签名方法。"

当我保存对象时(通过登录AWS并手动下载文件来验证它是否正常工作),我使用:

  s3 = boto3.client('s3', region_name='us-east-2', aws_access_key_id='XXXX', aws_secret_access_key='XXXX', config=Config(signature_version='s3v4'))

  s3.put_object(Bucket=self.bucket_name,Key=path, Body=temp_file.getvalue(),ACL='public-read')

然后,当我尝试获取网址时,我正在使用:

  s3 = boto3.client('s3', region_name='us-east-2', aws_access_key_id='XXXX', aws_secret_access_key='XXXX', config=Config(signature_version='s3v4'))

  url = s3.generate_presigned_url(
        'put_object', Params={
        'Bucket':self.pdffile_storage_bucket_name, 
        'Key':self.pdffile_url
        },
        ExpiresIn=604799,
    )

我在网上看到很多用户在谈论确保您的AWS访问密钥不包含任何特殊字符。我这样做了,我仍然遇到同样的问题。

3 个答案:

答案 0 :(得分:1)

您正在为上传而非下载生成预先签名的网址。你不想在这里put_object ......它是get_object

另外,正如@ThijsvanDien指出的那样,ACL='public-read'可能不是您想要的,在上传时 - 这使得任何拥有未签名网址的人都可以访问该对象。

答案 1 :(得分:1)

(经过 3 个多小时的调试,差点把键盘砸坏....)

在响应中,它会告诉您缺少哪个标头:

<Error>
    <Code>SignatureDoesNotMatch</Code>
    <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
    <!-- .... -->
    <CanonicalRequest>PUT (your pre-signed url)
    content-type:image/jpeg
    host:s3.eu-west-2.amazonaws.com
    x-amz-acl:

    content-type;host;x-amz-acl
    UNSIGNED-PAYLOAD</CanonicalRequest>

生成预签名 URL 时需要与 ACL 集匹配的 x-amz-acl 标头

def python_presign_url():
    return s3.generate_presigned_url('put_object', Params={
        'Bucket': bucket_name,
        'Key': filename,
        'ContentType': type,
        'ACL':'public-read' # your x-amz-acl
    })
curl -X PUT \
    -H "content-type: image/jpeg" \
    -H "Host: s3.eu-west-2.amazonaws.com" \
    -H "x-amz-acl: public-read" \
    -d @/path/to/upload/file.jpg "$PRE_SIGNED_URL"

答案 2 :(得分:0)

我尝试了来自许多不同地方的许多解决方案。没有一个对我有用。然后我在GitHub上找到了一个对我有用的解决方案。 Here是原始解决方案,只需复制粘贴其解决方案即可。

s3 = boto3.client('s3',region_name ='us-east-2', aws_access_key_id ='XXXX',aws_secret_access_key ='XXXX', config = Config(signature_version ='s3v4'), endpoint_url ='https://s3.us-east-2.amazonaws.com')