【问题标题】:boto3 signature doesn't match with S3boto3 签名与 S3 不匹配
【发布时间】:2016-10-13 05:41:39
【问题描述】:

我正在尝试使用boto3Heroku 上传到S3,但我不断收到错误<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>。我尝试使用pre-signed postpre-signed url,但错误仍然存​​在。我提供给 Heroku 以发出请求的凭证是我的根 AWSAccessKeyID 和密钥,所以我不应该有权限问题。我可以从命令行直接上传到 S3。

生成预签名帖子后返回的值:

{'fields': {'x-amz-signature': '26eff5417d0d11a25dd294b059a088e2be37a97f14713962f4240c9f4e33febb', 'x-amz-algorithm': 'AWS4-HMAC-SHA256', 'key': u'sound.m4a', 'x-amz-credential': u'<AWSAccessID>/20161011/us-east-1/s3/aws4_request', 'policy': u'eyJjb25kaXRpb25zIjogW3siYnVja2V0IjogImZ1dHVyZWZpbGVzIn0sIHsia2V5IjogInNvdW5kLm00YSJ9LCB7IngtYW16LWFsZ29yaXRobSI6ICJBV1M0LUhNQUMtU0hBMjU2In0sIHsieC1hbXotY3JlZGVudGlhbCI6ICJBS0lBSTdLRktCTkJTNEM0VktKQS8yMDE2MTAxMS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0sIHsieC1hbXotZGF0ZSI6ICIyMDE2MTAxMVQyMDM4NDlaIn1dLCAiZXhwaXJhdGlvbiI6ICIyMDE2LTEwLTExVDIxOjM4OjQ5WiJ9', 'x-amz-date': '20161011T203849Z'}, 'url': u'https://s3.amazonaws.com/bucketname'}

Heroku 上当前的代码:

@api.route('/post_track', methods=['POST'])
@login_required
def post_track():
    if request.method == 'POST':
        file = request.files['file']
        track = Track.upload_fromJSON(request.form.get('share'), request.form.get('title'))

        //Postgres entry
        conn = get_conn()
        with conn.cursor() as cur:
            cur.execute('INSERT INTO tracks(user_id, title, share)'
                    'VALUES (%s, %s, %s) RETURNING id;',
                    (track.user_id, track.title, track.share))
            track_id = cur.fetchone()[0]
            conn.commit()

            //Obtain pre-signed request
            signed_request = get_signed_request(track.title, request.form.get('type'), track_id, file)
            return json.dumps({'response':signed_request})


def get_signed_request(title, type, track_id, file):
    S3_BUCKET = os.environ.get('S3_BUCKET')
    file_name = title
    file_type = type
    region = 'us-east-1'
    s3 = boto3.client('s3', region_name=region, config=Config(signature_version='s3v4'))

    presigned_post = s3.generate_presigned_post(
        Bucket = S3_BUCKET,
        Key = file_name
    )

    files = {'file': file}

    r_response = requests.post(presigned_post["url"], data=presigned_post["fields"], files=files)

    print(r_response)
    print(r_response.text)

我最终将设置代码以将预签名请求返回到我的前端并从那里直接上传。只是将其作为测试运行。

【问题讨论】:

    标签: heroku amazon-s3 boto3


    【解决方案1】:

    我真的很难接受这个。我联系了 S3 支持,他们说他们收到的请求看起来不错,而且 Heroku 生成签名的方式一定有问题。我联系了 Heroku,他们并没有真正回应。解决问题的方法是删除我的 AWS 根访问并生成一个新的,然后使用新的访问 ID 重新配置 heroku。超级简单,但很奇怪这就是问题所在。希望这可以帮助处理同样问题的人。

    【讨论】:

    • 您是否从控制台下载的 csv 文件中获取密钥?该文件的末尾没有空行,这会导致某些工具(例如cat)显示% 来表明这一点。如果你复制了多余的字符,那么它就行不通了。顺便说一句,使用 root 帐户凭据不是一个好主意。最佳做法是对单个用户使用用户和角色。
    • @JordonPhillips 希望让它以 root 运行,以确保错误与任何权限问题无关。我很困惑 - 我正在查看的 csv 在一行上有 AWSAccessKeyID,在下面的一行上有 AWSSecretKey。您是说每个键的末尾都应该有一个空字符,例如_