浏览器

Mixed Content 混合内容警告:找出 HTTPS 页面里的 HTTP 资源

作者: · 最后核实

报错信息Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an insecure resource

混合内容警告的意思是:HTTPS 页面里有一部分文件是通过明文 HTTP 加载的。 页面本身加密了,那些 HTTP 资源没有,所以浏览器会拦截脚本和框架,对图片则尝试升级或拦截。结果是地址栏不再显示安全,严重时页面排版错乱、按钮点不动。

先判断是网站的问题还是你电脑的问题

混合内容几乎都是网站自己的代码造成的,访客修不了,也不该由访客修。少数情况下是浏览器扩展、或者某些网络在页面里注入了 HTTP 内容(比如运营商广告注入),用无痕窗口或换个网络就能排除。

先用 SSL 检测 确认证书本身没问题:

curl ssl.sh/example.com

然后用 混合内容扫描 扫页面,或者按 F12 打开开发者工具,在“控制台”里找以 “Mixed Content” 开头的行。

原因

混合内容有 4 种来源,最常见的是模板或文章里写死了 http:// 地址。

1. 模板或文章里写死了 http:// 地址

老文章、主题文件、编辑器经常保存绝对地址 http://。找出来:

curl -s https://example.com/ | grep -oE 'src="http://[^"]+"|href="http://[^"]+\.css"' | sort -u

2. CMS 的站点地址还是 HTTP

WordPress 之类的系统按保存的站点地址生成链接,那里写的还是 http://,生成的每个链接都不安全。

wp option update home 'https://example.com'
wp option update siteurl 'https://example.com'
wp search-replace 'http://example.com' 'https://example.com' --skip-columns=guid

没有 WP-CLI 的话,可以在宝塔面板的数据库管理里先备份,再用插件做批量替换。

3. 第三方资源不支持 HTTPS

老的统计代码、图床、外链 CDN 没有 HTTPS。图片放在阿里云 OSS、腾讯云 COS 或七牛等对象存储上的,要给自定义域名配置 HTTPS 证书,再把地址改成 https://;实在不支持的资源,换掉或者下载到自己服务器上。

4. 后端在代理后面,以为自己是 HTTP

TLS 在 CDN 或负载均衡上终止,源站收到的是 HTTP,程序就生成 http:// 链接。CDN 回源时传 X-Forwarded-Proto,并让程序信任它。

在各浏览器/系统上的样子

浏览器 显示内容
Chrome / Edge / 360 / QQ 浏览器 控制台:“Mixed Content: The page at ... was loaded over HTTPS, but requested an insecure ...”;网站信息里提示连接并非完全安全
Firefox 控制台:“已阻止载入混合活动内容”之类的提示;锁图标带警告
Safari 网页检查器控制台显示被拦截的不安全内容

站长怎么修

根本修法是把所有资源地址改成 https:// 或相对路径,upgrade-insecure-requests 只作兜底。

1. 所有资源地址改成 https:// 或相对路径。代码和数据库都要搜,不能只看首页。

2. 清理期间加一个兜底响应头:

add_header Content-Security-Policy "upgrade-insecure-requests" always;

宝塔面板在“网站 → 设置 → 配置文件”里加到 server 块中即可。

3. 告诉程序它在 HTTPS 后面。

proxy_set_header X-Forwarded-Proto $scheme;

4. HTTP 跳转 HTTPS,全部资源都正常加载后,再考虑开启 HSTS,让浏览器以后不再用 HTTP 访问你的网站。

5. 重新扫描。 用 混合内容扫描 复查,并看一遍关键页面的控制台。

常见问题

混合内容对访客有危险吗?

有。HTTPS 页面里的 HTTP 脚本或框架可以被网络路径上的任何人篡改,进而控制整个页面,所以浏览器会拦截。图片风险低一些,但仍会暴露你在看什么。

能在浏览器设置里允许不安全内容吗?

Chrome 可以按网站允许,但这只改了你自己的浏览器,而且会削弱这个网站的保护。作为访客建议保持拦截;作为站长,把地址改好,谁都不用改设置。

加了 upgrade-insecure-requests 就够了吗?

不一定。它会在请求发出前把 http:// 子资源改写成 https://,前提是那个资源本身支持 HTTPS。不支持 HTTPS 的外部资源照样加载失败,还是要替换或修好。

资料来源

  1. W3C Mixed Content 规范
  2. MDN:混合内容
  3. MDN: CSP upgrade-insecure-requests
  4. Mozilla Support: Mixed content blocking in Firefox