Python Flask AWS S3 EU Central |错误请求不支持您提供的授权机制。请使用AWS4-HMAC-SHA256

时间:2018-05-24 09:18:29

标签: python amazon-s3 flask request

首先我知道有许多类似的线程,我全部都是红色和S3 Docu(请不要关闭这个帖子)。修复无处不在:

只需将sugnature_version更改为v4,因为eu central是在2014年之后创建的,不再支持v2

我现在尝试了所有语法,但我仍然遇到错误。

session = boto3.Session(
    aws_access_key_id=app.config['MY_AWS_ID'],
    aws_secret_access_key=app.config['MY_AWS_SECRET'],
    region_name='eu-central-1'
)

s3 = session.client('s3', config=Config(signature_version='s3v4'))

presigned_post = s3.generate_presigned_post(
Bucket = 'mybucket',
Key = 'videos/' + file_name,
Fields = {"acl": "public-read", "Content-Type": file_type},
Conditions = [
  {"acl": "public-read"},
  {"Content-Type": file_type}
],
ExpiresIn = 3600
)

我试过到处改变它。我还将我的boto3安装降级为版本1.6.61.4.4,但也没有用。我将它恢复到最新版本,即boto3==1.7.26

错误:

InvalidRequest

The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.

每个帖子都建议使用相同的修复程序,可能它不起作用,因为我使用Python / Flask。有什么必须以不同的方式完成吗?

我正在尝试通过客户端将巨大的视频文件直接上传到S3,因此我需要签署请求。

修改

我想可能存在SSL问题。我正在测试localhost上的所有内容,use_ssl的默认选项是true

我尝试将此版本上传到实际网站(启用了SSL)。没有用,仍然是同样的错误。

我还尝试在use_ssl = False上使用localhost,仍然是同样的错误。

1 个答案:

答案 0 :(得分:0)

问题在于HTML以及我如何命名输入字段。我从一个较旧的教程中提取了一个示例,但您必须按照解释的方式构建表单here by amazon

我已经使用了他们提供的所有输入。我已经检查了我的响应,该响应是由我的sign_s3函数生成的,并且已经填充了表单中的所有相应字段。

这是我的签名功能:

# Sign request for direct file upload through client for video
@app.route('/sign_s3/<path:file_name_data>/<path:file_type_data>/<up_type>', methods=["GET", "POST"])
@login_required
@check_confirmed
def sign_s3(file_name_data, file_type_data, up_type):
    if "localhost" in request.url_root:
        if up_type == "profile_vid":
            file_name = str(current_user.id) + get_random_code(5) + "local-profil-video." + file_name_data.split(".")[-1]
        else:
            file_name = str(current_user.id) + str(randint(1,100)) + "local-post-video-temp." + file_name_data.split(".")[-1]
    else:
        if up_type == "profile_vid":
            file_name = str(current_user.id) + get_random_code(5) + "-profil-video." + file_name_data.split(".")[-1]
        else:
            file_name = str(current_user.id) + str(randint(1,100)) + "-post-video-temp." + file_name_data.split(".")[-1]

    file_type = file_type_data

    session = boto3.Session(
        aws_access_key_id=app.config['MY_AWS_ID'],
        aws_secret_access_key=app.config['MY_AWS_SECRET'],
        region_name='eu-central-1'
    )

    s3 = session.client('s3', config=Config(signature_version='s3v4'))

    presigned_post = s3.generate_presigned_post(
    Bucket = 'mybucket',
    Key = 'videos/' + file_name,
    Fields = {"acl": "public-read", "Content-Type": file_type},
    Conditions = [
      {"acl": "public-read"},
      {"Content-Type": file_type}
    ],
    ExpiresIn = 3600
    )

    if up_type == "profile_vid":
        if current_user.profile_video != None:
            delete_file_from_aws("videos/", current_user.profile_video)
        setattr(current_user, "profile_video", file_name)
    else:
        print ('post video has been uploaded, no need to delete or set here')

    db_session.commit()

    return json.dumps({'data': presigned_post, 'url': 'https://s3.eu-central-1.amazonaws.com/mybucket/' + 'videos/' + file_name, 'created_file_name' : file_name})

我查看了开发控制台中生成的响应,我有这些值:

enter image description here

我使用的HTML表单在这里,我没有使用所有未注释的输入字段。我只是将它们包括在内,因为亚马逊在他们的例子中展示了所有这些:

<form id="direct_s3_profile_video_form" class="form-horizontal" role="form" method="POST" enctype="multipart/form-data">
   <!-- Content-Type:  -->
   <input type="hidden" name="Content-Type">
   <!-- <input type="hidden" name="x-amz-meta-uuid"> --> 
   <!-- <input type="hidden" name="x-amz-server-side-encryption"> -->
   <input type="hidden" name="X-Amz-Credential">
   <input type="hidden" name="X-Amz-Algorithm">
   <input type="hidden" name="X-Amz-Date">                  
   <!-- Tags for File: --> 
   <!-- <input type="hidden"  name="x-amz-meta-tag"> -->
   <input type="hidden" name="Policy">
   <input type="hidden" name="X-Amz-Signature">
   <input id="NEW_fileupload_video" type="file" name="file" accept="video/*">                   
   <button type="submit"> Upload </button>
</form>

另请注意,文件输入必须位于底部,因为:

  

之后的元素将被忽略

在我的例子中,表单的值是动态创建的,所以我使用JS填充表单:

$('#direct_s3_profile_video_form').find('input[name="key"]').val(response_json_data.data.fields['key']);
$('#direct_s3_profile_video_form').find('input[name="acl"]').val(response_json_data.data.fields['acl']);
$('#direct_s3_profile_video_form').find('input[name="Content-Type"]').val(response_json_data.data.fields['Content-Type']);
$('#direct_s3_profile_video_form').find('input[name="X-Amz-Credential"]').val(response_json_data.data.fields['x-amz-credential']);
$('#direct_s3_profile_video_form').find('input[name="X-Amz-Algorithm"]').val(response_json_data.data.fields['x-amz-algorithm']);
$('#direct_s3_profile_video_form').find('input[name="X-Amz-Date"]').val(response_json_data.data.fields['x-amz-date']);
$('#direct_s3_profile_video_form').find('input[name="Policy"]').val(response_json_data.data.fields['policy']);
$('#direct_s3_profile_video_form').find('input[name="X-Amz-Signature"]').val(response_json_data.data.fields['x-amz-signature']);  
$('#direct_s3_profile_video_form').attr('action', 'https://mybucket.s3.amazonaws.com');