最直接有效的解决方式是在nginx https server块中添加add_header content-security-policy "upgrade-insecure-requests";,使浏览器自动将http资源请求升级为https,无需修改前端代码;同时需配置80端口301跳转至https,并在代理场景下透传x-forwarded-proto头确保后端生成https链接。

HTTPS 页面加载 HTTP 静态资源会触发浏览器的“混合内容”(Mixed Content)拦截,导致 CSS、JS、图片等资源被拒绝加载或静默失败。这不是 Nginx 本身的问题,而是现代浏览器的安全策略——它不会让安全页面引入非安全资源。解决的核心思路是:不让 HTTP 资源出现在 HTTPS 页面中,且不依赖前端代码大规模修改。
启用 CSP 自动升级机制
这是最轻量、见效最快的方案。在 Nginx 的 HTTPS server 块中添加响应头,告诉浏览器自动把页面内所有 http:// 资源请求升级为 https://:
- 只加在
listen 443 ssl的 server 块里,不要放在 HTTP(80 端口)配置中 - 写法示例:
add_header Content-Security-Policy "upgrade-insecure-requests"; - 若已存在其他 CSP 规则,需合并而非覆盖,例如:
"upgrade-insecure-requests; default-src 'self';" - 该指令仅影响当前页面发起的子资源请求(如
<img src="http://...?x-oss-process=image/resize,p_40">),不改超链接或重定向行为
强制全站走 HTTPS 入口
即使启用了自动升级,用户仍可能通过 http:// 直接访问,此时页面初始加载仍是 HTTP,CSP 头不生效,后续资源仍可能以 HTTP 发起。必须堵住这个入口:
- 新增一个监听 80 端口的 server 块
- 用
return 301 https://$host$request_uri;实现永久跳转 - 确保
server_name与 HTTPS 配置一致,避免跳转目标错误 - 跳转后,所有请求都从 HTTPS 开始,CSP 才能稳定生效
代理场景下透传协议信息
当 Nginx 作为反向代理,后端应用(如 Spring Boot、Node.js)生成 HTML 时拼接了硬编码的 http:// 链接,问题就出在这里。需要让后端知道“外面是 HTTPS”:
- 在 proxy_pass 前添加:
proxy_set_header X-Forwarded-Proto $scheme; - 同时建议加上:
proxy_set_header X-Forwarded-Port $server_port; - 后端应用需启用对
X-Forwarded-Proto的识别(如 Spring Boot 的server.forward-headers-strategy=framework) - 避免后端生成
http://example.com/static/app.js这类链接,应输出相对路径或协议无关路径(//example.com/static/app.js或/static/app.js)
静态资源由 Nginx 直接托管
如果静态文件(JS/CSS/图片)本就存放在服务器本地,最稳妥的方式是绕过后端,由 Nginx 直接响应:
- 用正则 location 精确匹配常见静态后缀:
location ~* \.(js|css|png|jpg|gif|woff2|svg|ico)$ - 配合
root或alias指向真实文件路径 - 顺带设置合理缓存头:
expires 1y;+add_header Cache-Control "public, immutable"; - 这样既避免代理转发路径错乱,又杜绝后端生成错误协议链接的可能











