WordPress 在反向代理后 HTTPS 重定向循环的解决方案✔️
阿瓦达咔哒
2025年05月15日 21:08
收录于文集
共1篇

摘要: 你是否也曾在 Docker 中运行 WordPress,并通过反向代理(如 NPM、Nginx)为其配置了精美的 HTTPS 域名,却不幸遭遇了无休止的 ERR_TOO_MANY_REDIRECTS 错误?别担心,你不是一个人!本文将深入剖析这个常见问题的根源,并为你揭示一个简单而强大的 wp-config.php 配置技巧,让你彻底摆脱重定向的噩梦。

(一) 噩梦的开始:当 HTTPS 遇上反向代理

想象一下这个场景:你在群晖(或其他宿主机)上通过 Docker 轻松部署了 WordPress,并且为了安全和专业,你使用了 Nginx Proxy Manager (NPM) 或其他反向代理工具,将你的域名(比如 https://a.b.com:8443)指向了这个 WordPress 实例。你满心欢喜地配置好了 SSL 证书,一切看起来都那么完美。

然而,当你尝试访问你的网站时,浏览器却无情地抛出了 ERR_TOO_MANY_REDIRECTS。页面在 http 和 https:// 之间疯狂跳转,仿佛陷入了一个无法逃脱的怪圈。

我的踩坑实录(可简述你的初始配置):

  • 网络架构: 群晖 Docker -> WordPress (容器端口 80 映射到宿主机 9092) + NPM (处理所有入站流量,包括 SSL)。

  • 域名与端口: https://a.b.com:8443 (因特殊原因未使用标准 443 端口)。

  • NPM 配置: 将 a.b.com:8443 的 HTTPS 流量转发到 WordPress 的 HTTP 地址 http://[群晖IP]:9092。

  • WordPress 初始配置: wp-config.php 和数据库中的 siteurl、home 均设置为最终的 HTTPS 地址 https://a.b.com:8443/。

结果?熟悉的重定向地狱。

(二) 为什么 WordPress 会“迷路”?重定向循环的根源

要理解这个问题,我们首先要知道 WordPress 是如何判断当前访问是 HTTP 还是 HTTPS 的。

当用户的请求链条是这样的:

浏览器 --(HTTPS)--> 反向代理 (NPM) --(HTTP)--> WordPress

  1. 反向代理的职责: NPM 接收到来自浏览器的 HTTPS 请求。它负责处理 SSL/TLS 加密解密。然后,它通常会以普通的 HTTP 方式将请求转发给后端的 WordPress 应用。这是常见的做法,称为“SSL 终止 (SSL Termination)”。

  2. WordPress 的视角: WordPress 直接感知到的是来自 NPM 的 HTTP 请求。

  3. 冲突点: 如果此时 WordPress 的 siteurl 和 home 设置为 https://...,WordPress 会认为:“我的配置是 HTTPS,但现在这个请求是 HTTP 的,这不安全/不正确,我必须把它重定向回 HTTPS!”

  4. 循环发生: WordPress 发出重定向指令,浏览器再次请求 HTTPS 地址,反向代理再次解密并以 HTTP 转发...周而复始。

(三) 柳暗花明:wp-config.php 中的关键一行

在我焦头烂额之际,一个关键的改动拯救了这一切。我并没有改变复杂的网络架构,而是在 WordPress 的核心配置文件 wp-config.php 中加入了以下代码片段:

define('FORCE_SSL_ADMIN', true); // 建议:强制后台使用 SSL

// ↓↓↓ 核心中的核心 ↓↓↓

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {

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

 $_SERVER['HTTP_HOST'] = $_SERVER["HTTP_X_FORWARDED_HOST"]; // 注意:NPM 或你的反向代理需要正确设置 X-Forwarded-Host

 $_SERVER['SERVER_PORT'] = $_SERVER["HTTP_X_FORWARDED_PORT"]; // 注意:NPM 或你的反向代理需要正确设置 X-Forwarded-Port

}

这段代码在做什么?

  • define('FORCE_SSL_ADMIN', true);: 这是一个好习惯,它会强制 WordPress 后台(/wp-admin/)始终使用 HTTPS。

  • if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'):

    • $_SERVER['HTTP_X_FORWARDED_PROTO']: 当反向代理转发请求时,它通常会添加一些特殊的 HTTP 头部信息来告诉后端应用原始请求的一些情况。X-Forwarded-Proto 就是这样一个头部,它表明原始客户端(浏览器)是使用什么协议(http 或 https://)连接到代理的。

    • 这行代码检查是否存在这个头部,并且其值是否为 https。

  • $_SERVER['HTTPS'] = 'on';: 如果上述条件成立(即原始请求是 HTTPS),这行代码会“欺骗”或“告知”WordPress:“嘿,当前这个请求实际上是通过 HTTPS 来的!” WordPress 内部的 is_ssl() 函数等就会因此返回 true。

  • $_SERVER['HTTP_HOST'] = $_SERVER["HTTP_X_FORWARDED_HOST"];:

    • X-Forwarded-Host 头部包含了原始请求的域名。

    • 这行代码将 PHP 用来判断当前请求主机名的 $_SERVER['HTTP_HOST'] 变量,设置为反向代理传递过来的原始主机名。这对于 WordPress 生成正确的链接至关重要,特别是当内部端口和外部访问域名/端口不一致时。

  • $_SERVER['SERVER_PORT'] = $_SERVER["HTTP_X_FORWARDED_PORT"];:

    • X-Forwarded-Port 头部包含了原始请求的端口号。

    • 这行代码将 PHP 用来判断当前请求端口的 $_SERVER['SERVER_PORT'] 变量,设置为反向代理传递过来的原始端口号。这对于非标准端口(如我的 :8443)的 HTTPS 访问尤为重要。

重要前提:确保你的反向代理正确设置了 X-Forwarded-* 头部! NPM 通常默认会做这件事。如果你使用其他代理,请检查其配置。

推荐的最佳实践:

  1. 在 wp-config.php 中加入上述关键代码。

  2. 将数据库中的 siteurl 和 home 仍然设置为你最终希望用户访问的、包含正确协议和端口的完整 HTTPS 地址,例如 https://a.b.com:8443/。

  3. 清除缓存: 清除浏览器缓存、CDN 缓存(如果使用)、以及 WordPress 可能有的缓存插

  4. 测试! 你的网站现在应该可以通过 HTTPS 正常访问,不再有重定向循环了。

WordPress 在反向代理环境下的 HTTPS 配置确实是一个常见的痛点,ERR_TOO_MANY_REDIRECTS 更是让人头疼。但正如我们所见,通过在 wp-config.php 中添加几行简单的代码,利用反向代理传递的 X-Forwarded-* 头部信息,我们就能让 WordPress 正确识别外部请求的真实情况,从而优雅地解决这个问题。

希望这篇文章能帮助到同样被此问题困扰的你,让你能更专注于内容创作,而不是配置的泥潭!如果你有其他技巧或经验,欢迎在评论区分享。