发布时间:2026-09-12 05:01 更新时间:2026-09-12 05:01 阅读量:0
给站点装好证书、Nginx 也配了 301 跳转到 https,地址栏却仍然显示“不安全”,点开提示发现证书本身是有效的。这种情况十有八九不是证书的问题,而是页面里还夹着通过 http 加载的资源,浏览器把它判定为混合内容(Mixed Content)。本文先带你确认问题到底出在证书还是资源,再给出定位方法和一套可以批量落地的修复思路,改完前后都能自查。
浏览器显示“不安全”的原因有好几种:证书过期、域名不匹配、证书链不完整、页面调用 http 资源、表单提交到 http 地址等。动手改代码之前,先花一分钟确认证书是真的没问题。用 openssl 直接看服务器返回的证书信息:
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates
输出里能看到证书的使用者、签发者和生效/过期时间。如果域名匹配、时间也在有效期内,那证书这一环基本可以排除。更全面的证书链检测可以用在线工具,或者用 openssl verify 配合根证书做校验,具体参数以官方文档为准。
确认证书没问题后,再看混合内容的定义:页面本身通过 https 打开,但其中某些子资源仍用 http 协议请求,浏览器就会认为这个页面不安全。浏览器把它分成两类:脚本、样式表、iframe、XHR 这类属于主动混合内容,默认会被直接阻止;而图片、音视频、字体这类属于被动混合内容,部分浏览器会自动升级为 https,升级失败时只是提示或占位不显示。主动混合内容最容易造成“页面白屏、样式错乱、接口报错”,也是最需要优先处理的。
最快的定位入口是浏览器的开发者工具。按 F12 打开后,先看 Console 面板,被阻止的混合内容会打印出明确警告,包含发起页面和被请求的 http 地址,照着改就行。接着切到 Security 面板,会看到页面被标记为不安全,并单独列出混合内容条目。Network 面板则可以把筛选框输入框里填上 http:// 做过滤,剩下的请求就是需要替换的目标;记得勾选 Disable cache 并刷新一次,避免缓存干扰判断。
如果页面很多、改完一次还想做回归,靠手工点开每个页面效率不高,可以用命令行先扫一遍首页输出的 HTML:
curl -s https://www.example.com/ | grep -o 'http://[^"]*' | sort -u | head -50
这条命令只能看到服务端返回的初始 HTML,通过 JavaScript 动态拼接出来的地址抓不到,所以还要配合 DevTools 复核。对于 WordPress、Typecho 这类站点,内容大多存在数据库里,模板和插件目录也常常硬编码了旧域名,可以直接在网站根目录做一次全量搜索:
grep -rIn --include="*.php" --include="*.html" --include="*.js" --include="*.css" \
-E "http://(www\.)?example\.com|http://cdn\.example\.com" /www/wwwroot/example.com
把结果里的行号和文件记下来,就能分清哪些是模板里写死的、哪些是插件配置项,改起来有的放矢。注意别把 http://www.w3.org、http://schemas 这类只作标识符用的字符串一起替换掉,它们不产生实际网络请求。
修复的核心思路只有一句话:让所有会发起网络请求的地址都走 https。数据库部分优先用 WP-CLI 处理,它对序列化数据有专门处理,比手工写 SQL 更稳妥。操作前务必先备份数据库和网站文件:
wp search-replace 'http://www.example.com' 'https://www.example.com' \
--all-tables --precise --report-changed-only
加上 --precise 会以更慢但更严谨的方式校验序列化数据,具体行为以官方文档为准;--report-changed-only 只输出真正被修改的行,方便评估影响范围。如果站点没有装 WP-CLI,也可以按官方推荐的 SQL 方式做替换,但涉及 postmeta 里的序列化数据要格外小心,长度字段不会自动更新,容易把数据写坏。
模板、插件里的硬编码地址可以先用 grep 生成待改清单,确认无误后再批量替换。下面这条命令是先列出文件再改,执行前建议先做一次不带 sed 的试跑:
grep -rl "http://www.example.com" /www/wwwroot/example.com --include="*.php" \
| xargs sed -i 's|http://www.example.com|https://www.example.com|g'
第三方资源要单独看:CDN 上的 JS、字体、图床、统计脚本,都要换成 https 地址。如果对方站点压根不支持 https,那只能换供应商或把资源下载到本地。用了 CDN 的站点还要检查 CDN 控制台里的回源协议、加速域名是否已经启用 https,并在改完后刷新缓存,否则旧内容可能还在边缘节点上。
有些站点历史内容太多,一时半会儿改不完,可以先用 CSP 的 upgrade-insecure-requests 做过渡,让浏览器把页面内的 http 请求自动升级为 https。在 Nginx 的 server 段加一行:
add_header Content-Security-Policy "upgrade-insecure-requests" always;
这只是一个兜底手段,资源服务器本身没开 https 时依然会失败,所以不能替代源头替换。另外这条指令的作用范围和浏览器支持情况以实际环境为准,上线前要在主流浏览器里各验证一遍。等全站替换完成,再考虑加 Strict-Transport-Security 头,因为一旦下发 HSTS,浏览器在 max-age 有效期内会强制走 https,回退成本较高。
收尾验证建议按这个顺序走:清空浏览器缓存与 CDN 缓存,重新打开首页、栏目页、文章页和后台,确认 Console 里不再有 Mixed Content 警告,地址栏正常显示锁标识;再用 curl 扫一遍主要页面的 HTML,确认没有残留的 http 资源地址。把这几步固化成上线检查项,以后换域名、换 CDN、上新品插件时照着走一遍,就能避免类似问题反复出现。
| 📑 | 📅 |
|---|---|
| 服务器磁盘被写满的排查流程:df与du定位、日志切割与清理注意事项 | 2026-09-11 |
| 宝塔面板安全加固:面板端口、安全入口、SSL与登录告警设置 | 2026-09-11 |
| Nginx 502/504 排查:从错误日志到PHP-FPM进程池状态 | 2026-09-10 |
| MySQL慢查询日志开启与参数分析:用mysqldumpslow定位拖慢网站的SQL | 2026-09-10 |
| 自建网站状态监控:Uptime Kuma部署与告警配置 | 2026-09-10 |
| phpMyAdmin导入大SQL超时:参数调整与命令行导入 | 2026-09-12 |
| 大文件上传总失败:php.ini与Nginx三处限制如何协调放行 | 2026-09-14 |
| Nginx反向代理缓存实战:proxy_cache_path配置与命中率排查 | 2026-09-15 |
| Let's Encrypt证书自动续期失败排查:certbot renew定时任务与webroot验证 | 2026-09-15 |
| WordPress数据库膨胀排查:wp_options自动加载与孤立表清理 | 2026-09-15 |