给 WordPress 配置 Nginx HTTPS 反向代理

给 WordPress 配置 Nginx HTTPS 反向代理后,网站的 CSS、JS 等静态资源链接都变成了 HTTP 协议,导致浏览器报混合内容错误,资源加载异常

1. 核心原因分析

WordPress 出现这个问题,本质是站点的 URL 配置和反向代理的协议传递不匹配,具体有两个关键原因:

  • WordPress 内部通过 siteurlhome 配置项存储站点域名和协议,如果这两个值是 http:// 开头,生成静态资源链接时会默认用 HTTP;
  • 反向代理后,WordPress 无法感知客户端实际用的是 HTTPS 协议,仍认为当前请求是 HTTP,因此输出的资源链接会带上 http:

2. 完整解决方案(分两步)

步骤 1:修正 Nginx 反向代理配置(传递 HTTPS 标识)

首先确保 Nginx 正确传递 HTTPS 协议信息给 WordPress,让 WordPress 知道客户端用的是 HTTPS:

upstream blog-backend {
    ip_hash;
    server 172.17.0.1:12660;
    server 127.0.0.1:12660;
}
server {
    listen 4008 ssl;
    server_name example.com;
    ssl_certificate /etc/nginx/certs/example.com.cer;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
    ssl_session_timeout 1h;
    resolver 8.8.8.8 1.1.1.1 valid=300s;
    resolver_timeout 5s;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    error_page 497 https://$http_host$request_uri;

    location / {
        proxy_pass http://blog-backend;
        proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
        proxy_set_header Host $http_host;
        proxy_set_header Port $server_port;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Scheme https;
        proxy_set_header X-Forwarded-Ssl on;
    }

    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_disable "msie6";

    client_max_body_size 800m;
}

步骤 2:修正 WordPress 配置(强制 HTTPS)

这一步是核心,需要让 WordPress 全局使用 HTTPS 协议生成链接,有一种方式:

方式 1:修改 wp-config.php(推荐,最稳定)

编辑 WordPress 根目录的 wp-config.php 文件,在 /* That's all, stop editing! Happy publishing. */ 之前添加以下代码:

// 强制 WordPress 使用 HTTPS 协议
define('WP_HOME', 'https://example.com:4008'); // 替换成你的域名
define('WP_SITEURL', 'https://example.com:4008'); // 替换成你的域名

// 告诉 WordPress 处于反向代理后的 HTTPS 环境
define('FORCE_SSL_ADMIN', true);
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
    $_SERVER['SERVER_PORT'] = 4008;
}

// 禁用 WordPress 自动修改链接(防止协议回退)
define('WP_CONTENT_URL', 'https://example.com:4008/wp-content');
define('COOKIE_SECURE', true); // 强制 Cookie 仅通过 HTTPS 传输
define('SESSION_COOKIE_SECURE', true);
Categories: 系统运维