证书装好了,站点也能用 https 打开,可地址栏那把小锁就是不出现,变成一个灰色感叹号。图片有几张裂了,某个滑块不动了,后台还偶尔跳回 http。这就是典型的混合内容(Mixed Content)——页面主体走了 HTTPS,但里面还引用着 http:// 的图片、CSS、JS。浏览器出于安全考虑,把这些请求要么标记为不安全,要么直接拦掉。
先定位到底是哪几个资源在拖后腿
别急着动数据库。按 F12 打开控制台,刷新页面,找红色或黄色的 Mixed Content 提示,它会明确写出被拦截的完整 URL。切到 Network 面板,把 Protocol 列打开,按协议排序,一眼就能看出哪些请求还是 http。
记下这些 URL 的规律很重要。如果都是自己域名下的 /wp-content/uploads/ 图片,那是数据库里存的旧链接;如果指向第三方域名,那是外部资源的问题;如果是某个插件目录下的 js,那多半是插件写死的。三种情况处理方式完全不同。
改站点地址,这一步最容易被漏掉
进后台「设置 → 常规」,把 WordPress 地址和站点地址两栏都改成 https 开头。如果这两栏是灰色不能编辑的,说明被 wp-config.php 里的常量锁定了,去文件里改:
define('WP_HOME', 'https://你的域名.com');
define('WP_SITEURL', 'https://你的域名.com');
批量替换数据库里的旧链接
文章正文、自定义字段、小工具配置里散落着大量 http:// 绝对路径。这里有个坑:不要用 SQL 的 REPLACE 直接改。WordPress 有很多序列化存储的数据(比如主题设置、部分插件配置),字符串长度是写死在里面的,直接替换会让长度对不上,配置整个失效。
用 WP-CLI 是最稳的做法,它会自动处理序列化:
wp search-replace 'http://你的域名.com' 'https://你的域名.com' --all-tables --dry-run
wp search-replace 'http://你的域名.com' 'https://你的域名.com' --all-tables
先跑 –dry-run 看会改多少条,心里有数了再去掉参数真跑。没有 SSH 权限的话,装 Better Search Replace 插件,效果一样,记得勾上「处理序列化数据」并先备份数据库。
主题和插件里硬编码的 http
有些老主题会在模板里直接写 <script src="http://cdn.xxx.com/jquery.js">。数据库替换管不到这里,只能翻代码:
grep -rn "http://" wp-content/themes/你的主题/ --include="*.php" --include="*.js" --include="*.css"
找到后改成 https,或者干脆去掉协议头写成 //cdn.xxx.com/,让浏览器跟随当前页面协议。插件里发现这种问题,先看有没有更新版本,改插件源码升级一次就白改了。
用了 CDN 或反向代理?还有一个额外的坑
如果 HTTPS 是在 Nginx、Cloudflare 或负载均衡层终止的,回源到 PHP 时走的是 http,那么 PHP 里的 $_SERVER['HTTPS'] 是空的。WordPress 据此判断当前不是 HTTPS,生成的链接就全变回 http,还可能引发重定向死循环。在 wp-config.php 顶部、require_once ABSPATH . 'wp-settings.php'; 这行之前加上:
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
前提是代理层确实传了这个头。Nginx 里对应的配置是 proxy_set_header X-Forwarded-Proto $scheme;。
第三方资源不支持 HTTPS 怎么办
偶尔会碰到某个统计脚本、老图床只有 http。没有捷径可走,要么联系对方开 HTTPS,要么把资源下载到自己服务器上引用,要么换服务商。别指望浏览器网开一面,Chrome 对主动混合内容(js、iframe)是直接拦截的。
过渡期可以在响应头里加一行 Content-Security-Policy: upgrade-insecure-requests,让浏览器自动把 http 请求升级成 https。但这只是应急,对方服务器本身不支持 https 的话,升级后照样 404。
最后补上强制跳转
清理干净之后,在 Nginx 里把 http 全站转到 https,避免有人从旧链接进来又跑回不安全的版本:
server {
listen 80;
server_name 你的域名.com www.你的域名.com;
return 301 https://$host$request_uri;
}
改完 nginx -t 检查语法,再 systemctl reload nginx。然后清一遍所有缓存——页面缓存插件、CDN 缓存、浏览器强制刷新,三层都要清,不然你看到的还是旧页面。
常见问题
问:改完之后小锁出来了,但过几天又变回感叹号,怎么回事?
八成是新发的文章里又插入了 http 图片,或者某个插件更新后重新写入了旧链接。检查一下媒体库上传时生成的 URL 是不是 https,以及有没有从别处复制粘贴带 http 的内容。
问:只有后台有问题,前台正常,是什么原因?
优先查 wp-config.php 里的 FORCE_SSL_ADMIN 有没有设成 true,以及上面那段 X-Forwarded-Proto 判断加了没有。反代场景下后台出问题的概率比前台高得多。
问:数据库替换会不会把文章内容改坏?
用 WP-CLI 或支持序列化的插件就不会。真正危险的是直接在 phpMyAdmin 里跑 UPDATE … REPLACE 语句。无论用哪种方式,动手前先导一份 sql 备份,出事能退回去。
如果你按这些步骤走完还是有几个资源顽固地报混合内容,把控制台里的报错 URL 贴到 fenij.com 的评论区,我看看是哪一类,帮你判断该从哪下手。