发布时间:2026-09-27 05:01 更新时间:2026-09-27 05:01 阅读量:0
证书装好、强制跳转也配了,浏览器地址栏却还是那句「不安全」,点开详情写的往往是「此页面包含不安全内容」。这类问题就是混合内容:主文档走的是 https,页面里却还引用着 http 的图片、脚本、样式或者接口地址。对外行来说小锁不亮像是个小瑕疵,实际上它会让部分浏览器直接拦截脚本和样式,页面错版、统计失效、支付回调被挡都可能由此而来。下面这套流程,用浏览器控制台先摸清范围,再用 curl 和命令行批量筛源码,逐条定位并清掉。
打开出问题的页面,按 F12 调出开发者工具,切到 Console(控制台)。现代浏览器会把混合内容单独归类成 Mixed Content,并给出两条线:一条是「已拦截」的,通常是脚本、样式、iframe、XHR 这类会改变页面行为或安全性的资源;另一条是「已升级」或「警告」的,一般是图片、音视频等被动资源,浏览器可能自动把 http 换成 https 尝试加载,也可能只是提示。逐条点开,记录下完整 URL 和它出现在哪个文件里。
光看控制台还不够,切到 Network(网络)面板,按 Protocol 列排序或者直接筛选 http://,能看到这次请求里到底有多少资源还在走明文。如果页面很长、资源很多,可以在 Console 里跑一段小脚本,把当前文档里所有 http 属性扫出来,比肉眼翻快得多:
// 在浏览器控制台执行,列出当前页面中所有 http:// 引用
[...document.querySelectorAll('[src],[href]')]
.map(el => el.src || el.href)
.filter(u => u && u.startsWith('http://'))
.forEach((u, i) => console.log(i, u));
注意这只是扫当前 DOM,动态插入的元素、CSS 里 background-image 引用的地址、内联样式里的 url() 都扫不到,后面还要靠源码和 curl 补上。
控制台看到的是渲染后的结果,很多 http 地址藏在前端模板、插件输出的 HTML 段落或者数据库字段里。最直接的办法是把页面 HTML 抓下来,用 grep 把 http:// 全部捞出来:
# 抓取线上页面并筛选明文 http 资源
curl -sSL https://www.example.com/ -o page.html
grep -oE 'http://[^"'"'"' )]+' page.html | sort -u
如果是压缩输出,加 --compressed 让 curl 自动解压
curl -sSL --compressed https://www.example.com/ -o page.html
把结果按域名归类,通常能看出规律:全站都在用的 CDN 域名、某个统计脚本、某个插件带的老地址、某张写死在文章里的图。这时不要急着一条条改,先判断来源分层。
第一层是站点自身配置,比如 WordPress 后台的 siteurl、主题里硬编码的地址、宝塔面板里站点绑定域名的方式。这类问题改一处就能全站生效,优先级最高。第二层是数据库正文里写死的 http 图片地址,改起来要动内容表,建议先备份再批量替换,且替换时注意别把 https 里本来就正确的地址改坏。第三层是第三方服务给的地址,比如旧版统计代码、外链字体、第三方评论系统,这些要看对方是否支持 https,不支持就只能换服务或本地化。
顺带提醒一句,curl 抓到的和浏览器实际执行的可能仍有差异,因为有些资源是 JS 运行时拼出来的。所以控制台和 curl 两条线要交叉验证,别只信一边。
定位清楚后,修复顺序建议从「影响面大、改一处生效」的开始。站点层面的地址统一走 https,数据库里的老地址用 SQL 或 WP-CLI 批量替换,插件和主题里硬编码的地址逐个改掉。改完之后不要只刷新首页,用 curl 对多个页面类型做一次验证:
# 批量检查几个典型页面是否还有明文资源
for u in / /about/ /blog/ /contact/; do
echo "== $u =="
curl -sSL --compressed "https://www.example.com$u" \
| grep -oE 'http://[^"'"'"' )]+' | sort -u
done
常见的坑有三个。一是只改了首页模板,文章内页里作者手动插入的 http 图片还在,这类要全站扫。二是替换时用了全局字符串替换,把 https:// 里的内容也误伤,建议匹配时带上词边界或先备份再替换。三是图片、脚本虽然换成了 https,但对方域名证书本身有问题或者只支持 http,这时换回相对协议(//example.com/a.js)往往更稳妥,或者干脆把资源下到本地站内。
还有一个容易被忽略的点:如果站点前面挂了 CDN,CDN 回源和缓存里可能还留着旧的 HTML,改完源码后记得刷新对应 URL 的缓存,再复测。关于缓存刷新顺序,站内另有文章细讲,这里只强调验证前先刷。
最后做一次全量确认:用浏览器打开不同页面看小锁状态,控制台不再报 Mixed Content,Network 面板里 http:// 清零。如果还有残留,按控制台给出的文件路径回到源码里找,通常都能对上。混合内容不是靠一次替换就能一劳永逸的事,新发文章、新装插件都可能重新引入明文地址,把上面这段 curl 检查写进上线前的检查清单,比出问题后再救火划算得多。
| 📑 | 📅 |
|---|---|
| 宝塔面板部署 WordPress 后固定链接 404:伪静态规则加载顺序与 try_files 排查 | 2026-09-27 |
| 网站301与302混用导致权重分散:跳转类型选择与生效验证 | 2026-09-27 |
| WordPress后台被暴力撞库告警:登录限速与日志加固 | 2026-09-26 |
| 域名下PC站与m站SEO冲突:canonical、自适应与UA跳转取舍 | 2026-09-26 |
| 宝塔面板升级后网站打不开:PHP扩展、Nginx配置与面板服务逐项回滚排查 | 2026-09-26 |
| MySQL被OOM Kill排查:swap、buffer pool与监控取舍 | 2026-09-27 |
| Nginx resolver 域名解析缓存:反代上游换 IP 后仍走旧地址的排查 | 2026-09-27 |
| 宝塔面板日志被CDN节点IP填满:log_format与real_ip联动调整 | 2026-09-27 |
| WordPress 数据库表前缀修改实战:从 wp-config 到 SQL 批量改名 | 2026-09-27 |
| Nginx泛域名证书自动签发:acme.sh DNS验证与泛解析站点批量部署 | 2026-09-27 |