javascript - XMLHttpRequest 端点在签署 S3 请求时被阻止,因为没有 HTTPS,尽管一切都在 HTTPS 上

标签 javascript python ssl xmlhttprequest

我正在尝试对一个巨大的视频上传进行签名,因为我想将它直接上传到 S3。它在本地主机上工作,但在我的实时站点上它无法签署请求,因为:

Mixed Content: The page at 'https://www.example.com/profile' was loaded
over HTTPS, but requested an insecure XMLHttpRequest endpoint 
'http://www.example.com/sign_s3/?file_name=17mbvid.mp4&file_type=video/mp4'. 
This request has been blocked; the content must be served over HTTPS.

我在 heroku 上托管所有内容,每个页面都已经使用 HTTPS,并且不可能在 HTTP 中打开它,因为我将所有流量重定向到 HTTPS。我正在使用 letsencrypt SSL 证书。

到目前为止,我不知道去哪里找,我找到的唯一信息是我需要一个有效的 SSL 证书,我已经拥有了。

这是 JS 函数:

function getSignedRequest(file) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/sign_s3?file_name=" + file.name + "&file_type=" + file.type);
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                console.log('got signed request');              
                var response = JSON.parse(xhr.responseText);
                console.log(response);
                console.log('uploadFile', response.url)
                uploadFile(file, response.data, response.url);
            } else {
                console.log("Could not get signed URL.");
            }
        }
    };
    //console.log('send');  
    xhr.send();
}

在控制台出现错误后,我立即看到了这个控制台日志:

Could not get signed URL.

这意味着它在这里失败了:

if (xhr.status === 200)

在服务器上:

@app.route('/sign_s3/', methods=["GET", "POST"])
@login_required
@check_confirmed
def sign_s3():
    if "localhost" in request.url_root:
        file_name = str(current_user.id) + "local-profil-video." + request.args.get('file_name').split(".")[-1]
    else:
        file_name = str(current_user.id) + "-profil-video." + request.args.get('file_name').split(".")[-1]

    file_type = request.args.get('file_type')

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

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

    if current_user.profile_video != None:
        delete_file_from_aws("videos/", current_user.profile_video)
    setattr(current_user, "profile_video", file_name)
    db_session.commit()

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

最佳答案

经过几个小时的研究,我决定重建这个函数并使用我更熟悉的 AJAX get。我还将传递/接收查询字符串参数的方式更改为最佳方式,这实际上在 flask/python 中使用。

function getSignedRequest(file) {
$.ajax({
    url : "/sign_s3/" + file.name + "/" + file.type,
    type : "get",
    success : function(response) {
        console.log("success file up, follow", response);   
        var json_response = JSON.parse(response);
        console.log(json_response);
        uploadFile(file, json_response.data, json_response.url);
    },
    error : function(xhr) {
        console.log("file up failed", xhr);
    }
});

在服务器端,我更改了接收file.namefile.type 的方式:

# Sign request for direct file upload through client for video
@app.route('/sign_s3/<path:file_name_data>/<path:file_type_data>', methods=["GET", "POST"])
@login_required
@check_confirmed
def sign_s3(file_name_data, file_type_data):
    #etc...

现在它完美运行了。我认为我在服务器上接收查询字符串参数的方式不正确,可能它也适用于旧的 getSignedRequest 函数(未经测试)。

关于javascript - XMLHttpRequest 端点在签署 S3 请求时被阻止,因为没有 HTTPS,尽管一切都在 HTTPS 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50352091/

相关文章:

linux - 类 Unix 平台的 FTP GUI 客户端,支持 TLS/SSL/SFTP

c# - HttpWebRequest 与使用 SSL 的 Fiddler

javascript - 根据 callback(true)/callback(false) 执行操作

JavaScript 正则表达式 (x)

javascript - 内容不显示

尝试更改表时 Python MySQLdb 错误

python - 将 float 限制为两位小数

JavaScript/HTML/CSS - 一个页面上的多个表单

python - 如何将 .py 文件导入 Ansible 模块?

reactjs - React.js、nginx 和 SSL