boto3 签名与 S3 不匹配

boto3 signature doesn't match with S3

我正在尝试使用 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。

在生成预签名 post 后编辑的值 return:

{'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)

我最终会将代码设置为 return 到我的前端的预签名请求,并从那里直接上传。只是作为测试这样做 运行。

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