最直接有效的办法是用csp响应头upgrade-insecure-requests强制浏览器将http子资源升级为https;补充方案为nginx反向代理伪装http后端为https;兜底方案用sub_filter替换响应体中的http链接。

最直接有效的办法是让浏览器自动把页面里所有 http:// 请求升级成 https://,不用改前端代码,也不依赖后端是否支持 HTTPS。
首选方案:用 CSP 响应头强制升级
在 Nginx 的 HTTPS server 块中添加这一行:
add_header Content-Security-Policy "upgrade-insecure-requests" always;
-
upgrade-insecure-requests告诉浏览器:当前页面下所有不安全的 HTTP 子资源请求(图片、脚本、API、样式等),一律升为 HTTPS 发出 -
always确保即使返回 304 或错误状态码,这个头也不会丢失 - 只要页面本身是 HTTPS 加载的,且目标域名实际支持 HTTPS(比如 CDN 或后端已配好证书),升级后就能正常加载
补充方案:反向代理“伪装”HTTP 后端为 HTTPS
当后端服务确实无法启用 HTTPS(如内网 Spring Boot、老旧设备接口),可让 Nginx 对外提供 HTTPS,对内仍走 HTTP:
location ^~ /api/ {
proxy_pass http://192.168.1.10:8080/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
- 前端请求
https://yoursite.com/api/login,Nginx 转发到http://192.168.1.10:8080/login - 浏览器看到的全程都是 HTTPS,不会触发混合内容拦截
- 关键是
X-Forwarded-Proto $scheme,让后端知道原始请求是 HTTPS,避免重定向出错
兜底方案:用 sub_filter 替换响应体中的 HTTP 链接
适用于硬编码在 HTML/JS/CSS/JSON 中的 http:// 地址(比如 <img src="http://cdn.com/a.jpg?x-oss-process=image/resize,p_40">):
location / {
proxy_pass http://backend;
gzip off;
proxy_set_header Accept-Encoding "";
sub_filter_types text/html application/javascript text/css application/json;
sub_filter 'src="http://' 'src="https://';
sub_filter "href='http://" "href='https://";
sub_filter_once off;
}
- 必须关掉
gzip和brotli,否则 sub_filter 失效 -
sub_filter_types要显式列出 JS、CSS、JSON 等类型,默认只处理 HTML - 用带引号和属性名的写法(如
src="http://),避免误替换http://localhost或协议相对 URL
验证是否生效
- 打开 Chrome 开发者工具 → Network 标签页 → 刷新页面
- 查看任意 HTML 请求的 Response Headers,确认含
Content-Security-Policy: upgrade-insecure-requests - 在 Network 中筛选 XHR 或 Img,检查所有请求地址是否已变为
https:// - 清除浏览器缓存再测,旧响应可能没带新 Header
不复杂但容易忽略











