You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

S3签名请求时XMLHttpRequest端点因非HTTPS被拦截问题排查

问题分析与解决方案

首先,你的核心问题是混合内容(Mixed Content)错误:页面通过HTTPS加载,但AJAX请求却发起了HTTP协议的请求,浏览器出于安全策略直接拦截了这个不安全的请求,导致签名接口调用失败。

为什么会出现这个问题?

虽然你在前端写的是相对路径/sign_s3,但浏览器却将其解析为http://www.example.com/sign_s3,而非继承页面的HTTPS协议。结合Heroku部署环境,主要有以下几个可能的根源:


可能的原因及对应解决方案

1. Flask应用未正确识别Heroku的反向代理协议头

Heroku的请求是通过反向代理转发的,它会通过X-Forwarded-Proto头传递原始请求的HTTPS协议,但Flask默认不会信任这个头,导致应用误以为请求是HTTP协议,进而影响URL解析。

解决方案:
在Flask应用中添加代理头处理配置,让应用正确识别HTTPS协议:

from flask import Flask
from werkzeug.middleware.proxy_fix import ProxyFix

app = Flask(__name__)

# 信任反向代理传递的协议、主机头等信息
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)

# 配置默认URL协议为HTTPS
app.config['PREFERRED_URL_SCHEME'] = 'https'

# 确保Cookie仅通过HTTPS传输(增强安全性)
app.config['SESSION_COOKIE_SECURE'] = True
app.config['REMEMBER_COOKIE_SECURE'] = True

2. HTML模板中存在HTTP协议的<base>标签

如果你的页面模板里设置了<base href="http://www.example.com/">,浏览器会基于这个HTTP地址解析所有相对路径,导致AJAX请求变成HTTP协议。

解决方案:

  • 检查页面的HTML代码,移除或修改<base>标签为HTTPS:
    <!-- 移除错误的base标签,或者修改为HTTPS -->
    <base href="https://www.example.com/">
    

3. 前端代码未显式指定协议(可选优化)

虽然相对路径理论上应该继承页面协议,但可以通过显式构造URL的方式避免解析错误:

function getSignedRequest(file) {
  // 显式使用当前页面的协议和主机构造URL
  const url = `${window.location.protocol}//${window.location.host}/sign_s3?file_name=${encodeURIComponent(file.name)}&file_type=${encodeURIComponent(file.type)}`;
  var xhr = new XMLHttpRequest();
  xhr.open("GET", url);
  
  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.");
      }
    }
  };
  xhr.send();
}

同时注意用encodeURIComponent对文件名和类型编码,避免特殊字符导致的URL解析问题。

4. Heroku强制HTTPS跳转配置不完整

确保你已经启用了Heroku的强制HTTPS跳转:

# 安装SSL重定向插件
heroku plugins:install heroku-ssl-redirect
# 开启强制HTTPS跳转
heroku config:set SSL_REDIRECT=true

另外,检查SSL证书状态是否正常:

heroku certs

确认证书状态为Trust,且覆盖了你的域名。

5. 浏览器缓存旧的HTTP资源

浏览器可能缓存了旧的HTTP版本页面或脚本,导致请求逻辑未更新。可以:

  • 清除浏览器缓存(Ctrl+Shift+R强制刷新)
  • 在静态资源文件名后添加版本号(比如app.js?v=2),强制浏览器加载新资源

内容的提问来源于stack exchange,提问作者Roman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:04:47