时间:2025年9月28日—10月6日

主机:AMD 5700U

应用:WordPress

bug是否消失:是

bug是否彻底解决:是

bug严重等级:红色


问题描述

网站启用 SSL 证书后,访问 https:// 域名时出现重定向错误:

  • 部分页面仍通过 HTTP 加载,导致混合内容警告;

  • WordPress 后台无法登录,浏览器提示 ERR_TOO_MANY_REDIRECTS

  • 尝试清理缓存后问题依旧。


排查问题

检查wp-config.php设置

检查 WordPress 配置。

打开wp-config.php,确认站点URL已强制为 HTTPS:

define('WP_HOME','https://xxx.asxn.top'); 
define('WP_SITEURL','https://xxx.asxn.top');

配置正确,但访问仍出现重定向错误。

回退到http

尝试将站点临时回退为HTTP,以确认问题是否出在WordPress本身。

测试结果:HTTP模式下页面可正常加载,后台登录无异常,说明问题集中在HTTPS处理链上。

更换证书

怀疑证书存在兼容或验证问题,于是将原本的Let’s Encrypt证书更换为阿里云免费证书。

替换后问题依旧,排除证书签发与验证环节异常,并替换回Let’s Encrypt证书。

检查openrest配置

检查网站配置文件,发现目前的配置中:

proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $server_name;

这两行虽然看起来在传递 HTTPS,但实际上放的位置不对 ——并未在转发请求时生效(尤其是多 location 时容易被覆盖)

间接导致在 server {} 外层全局生效不稳定,

WordPress 后端期望接收到的请求头为:

X-Forwarded-Proto: https
X-Forwarded-For: <用户真实IP>
Host: xxx.asxn.top

但这里的 proxy_set_header X-Forwarded-Proto https; 在 server 块内,而非 location 块内,

proxy_pass 又定义在 / location 里,所以 WordPress 实际接收到的头可能为空(被覆盖)。

这样WordPress 会认为「我现在是 http://xxx.asxn.top」,于是它就:

➡️ 自动跳转到 https://xxx.asxn.top

➡️ Nginx 又重定向回 HTTP 内部端口(127.0.0.1:9999)

➡️ 无限循环 🔁

配置修改

server {
    listen 8080;
    listen 8443 ssl;
    server_name xxx.asxn.top;

    index index.php index.html index.htm default.php default.htm default.html;
    access_log /www/sites/xxx.asxn.top/log/access.log main;
    error_log /www/sites/xxx.asxn.top/log/error.log;

    location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) {
        return 404;
    }

    location ^~ /.well-known {
        allow all;
        root /usr/share/nginx/html;
    }

    if ($uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$") {
        return 403;
    }

    http2 on;
    
    # SSL部分已省略(含证书路径、加密算法配置)

    # 当 http 访问时自动重定向 https
    error_page 497 https://$host$request_uri;

    location / {
        proxy_pass http://127.0.0.1:9999;

        # 关键修复点
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

验证结果

修复后,重启容器和openrest,在隐私端口测试:

网站可通过 HTTPS 正常访问;后台登录与前台跳转均正常,SSL 检测通过。


盘点总结

WordPress的内置机制:

会根据访问协议(HTTP / HTTPS)和你配置的 WP_HOME、WP_SITEURL 自动重定向。

换句话说,当配置中写明https://xxx.asxn.top,

但 WordPress 实际接收到的请求却是 HTTP(因为反代内部转发给 127.0.0.1:9999)

它就会误以为:“哦,用户访问错协议了,我帮他重定向到 HTTPS!”

结果悲剧出现了:

  1. 浏览器访问 https://xxx.asxn.top

  2. Nginx 转发给 WordPress(内部 HTTP)

  3. WordPress 又强制跳到 HTTPS

  4. Nginx 再转回来 HTTP(因为内部通信)

  5. WordPress 再跳……

  6. 无限循环造成ERR_TOO_MANY_REDIRECTS

解决方法生效的原因

新增配置:

proxy_set_header X-Forwarded-Proto $scheme;

其中$scheme是Nginx的变量,自动识别当前访问协议(HTTP 或 HTTPS)

这样反代转发时WordPress就能正确接收到:

HTTP_X_FORWARDED_PROTO=https

于是那行在wp-config.php里的逻辑:

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {

    $_SERVER['HTTPS'] = 'on';

}

就会生效

WordPress 终于知道自己在 HTTPS 下了,不再乱跳。

总结一句话

根本原因在于——Nginx 没告诉 WordPress「我其实是 HTTPS」。

现在补上这一行 proxy_set_header X-Forwarded-Proto $scheme;

就等于在它俩之间“翻译”了访问协议,让WordPress明白自己当前运行在HTTPS环境中。

文章润色

chatgpt