如何在 Amazon Load Balancer 后面修复 WordPress HTTPS 问题?

How to fix WordPress HTTPS issues when behind an Amazon Load Balancer?

我以前遇到过这个问题。当 运行 WordPress(或其他 PHP 脚本)在 Amazon 的 EC2 负载均衡器后面时,脚本没有意识到它们在 https:// 协议上 运行 并导致诸如无休止的问题重定向循环和 HTTPS 警告 ("Some content on this page is being requested in a non-secure way...")。

我在这里找到了解决方案,但需要修改 WordPress 核心,这不利于可更新性: https://wordpress.org/support/topic/when-behind-amazon-web-services-elastic-load-balancer-causes-endless-redirect

有没有办法在不修改 WordPress 核心的情况下解决这个问题?我正在使用 Apache 2.2。

与 link 一样,您给出了建议,对于 WordPress,问题出在 is_ssl() 函数上,该函数与大多数 PHP 软件一样显式检查 $_SERVER['HTTPS']$_SERVER['SERVER_PORT']检查当前页面是否在https://上下文中被访问。

当您的页面通过 HTTPS 访问时,但 Amazon 负载均衡器正在执行 SSL 卸载并实际在 non-SSL 端口 80、网络服务器 PHP 或任何其他内容上请求您的内容没关系,不明白或看不到它是通过 https:// 访问的。

解决这个问题的方法是 Amazon 的 ELB 发送 de-facto 标准 X-Forwarded-Proto HTTP header,我们可以使用它来确定客户端是哪个协议 实际上 在负载均衡器的另一端使用。

对于 Apache 2.2,您可以使用以下内容:

<IfModule mod_setenvif.c>
  SetEnvIf X-Forwarded-Proto "^https$" HTTPS
</IfModule>

这只是读取X-Forwarded-Proto header。如果此值等于 https,则 HTTPS 环境变量设置为 1。 PHP 会看到这个环境变量,最终,它将变成 $_SERVER['HTTPS'] 等于 1 —— 就像“真正的”本机 SSL 请求一样。

WordPress documentation 的另一个选项是将其添加到您的 wp-config。php:

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
       $_SERVER['HTTPS']='on';

不幸的是,以上都没有为我解决混合内容错误。然而,起作用的是将协议添加到 wp-config.php 中的 WP_HOME && WP_SITEURL 变量,例如

define( 'WP_HOME', 'https://' . $_SERVER['HTTP_HOST']); define( 'WP_SITEURL', WP_HOME );

之后,源中的所有 URL 都以 https 开头,所有混合内容错误都消失了。

在 WordPress 中使用 ssl 时,使用这 4 步方法消除重定向循环和混合内容问题。

1) 在数据库中将 'http://' 替换为 '//' - 这将创建图像和其他资产的所有相关 url

2) 在 wp-config 中,定义通用 wp_home 和 wp_siteurl 变量。

define('WP_HOME','//'. $_SERVER['SERVER_NAME']);
define('WP_SITEURL','//'. $_SERVER['SERVER_NAME']);

3) 如果您正在使用负载平衡器,请使用 'HTTP_X_FORWARDED_PROTO' 服务器变量来确定使用的协议。为此,请在 wp-config

中添加此行
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)
$_SERVER['HTTPS']='on';

4) 最后在 .htaccess 中,如果您在负载均衡器后面,请使用此行将所有流量重定向到 https。

 # http to https
 RewriteCond %{HTTP:X-Forwarded-Proto} =http
 RewriteRule . https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

如果其他人正在寻找与此等效的 Nginx,您需要执行以下操作:

对于重写设置,您应该在 server 块下添加以下内容:

if ($http_x_forwarded_proto != 'https') {
    rewrite ^ https://$host$request_uri? permanent;
}

为了设置 HTTPS 参数,您应该在 location ~ \.php$ 块下添加以下内容:

if ($http_x_forwarded_proto = 'https') {
    set $fe_https 'on';
}
fastcgi_param HTTPS $fe_https;

记得删除任何其他 fastcgi_param HTTPS 命令(如果有)(我的 fastcgi_params 文件中有)。

我的服务器环境是: Ubuntu 20.04.3 LTS, PHP 8.0.11, nginx/1.18.0

/etc/nginx/sites-available/default 中的以下设置对我有用:

server {

    listen 80;
    listen [::]:80;
    root /var/www/html;
    index  index.php index.html index.htm;
    server_name ChangeDomainName.com www.ChangeDomainName.com;

    if ($http_x_forwarded_proto != 'https') {
        rewrite ^ https://$host$request_uri? permanent;
    }

    location / {
            try_files $uri $uri/ /index.php?$args;
    }
    location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/run/php/php8.0-fpm.sock;
            if ($http_x_forwarded_proto = 'https') {
                set $fe_https 'on';
            }
            fastcgi_param HTTPS $fe_https;
            fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}