网站统一HTTPS与主域名的方法

本文以www.example.com作为主域名,把example.com和HTTP访问统一到HTTPS主站。域名均为占位,请替换为实际名称。适用于普通网站页面;已有接口、支付回调、WebDAV等入口时,要逐项评估请求方法与兼容性,不能把全站重定向当成无影响的外观修改。住宅云不适用于建站。

先满足证书和站点前提

  1. 确认根域名与www均指向预期接入服务,检查是否存在旧AAAA记录。
  2. 先分别直接打开两个HTTPS名称,证书应覆盖这两个名称且有效;备用域名发生TLS错误时,浏览器会在收到跳转之前失败。
  3. 保留当前主站443配置及PHP、代理、静态资源规则,记录证书文件位置和原配置。
  4. 使用CDN时确认TLS终止位置及CDN到源站连接模式;本篇Nginx示例不代替CDN侧设置。

先用临时跳转验证

以下只展示需要调整的HTTP及备用域名HTTPS块。现有www主站443块继续保留,不要用这两段覆盖主站业务配置。证书路径必须替换为已存在的实际文件,并确认完整链及私钥权限。

server {
    listen 80;
    server_name example.com www.example.com;
    return 302 https://www.example.com$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    return 302 https://www.example.com$request_uri;
}

目标域名写成固定名称,避免把任意Host反射到Location。$request_uri会携带原路径及查询参数。若证书管理工具保留了ACME验证location,应沿用该工具的正确配置,不盲目删除。已有相同server_name块时修改原块,避免重复匹配。

sudo nginx -t
sudo systemctl reload nginx

按四种入口验证完整跳转链

curl -I 'http://example.com/test-path?from=check'
curl -I 'http://www.example.com/test-path?from=check'
curl -I 'https://example.com/test-path?from=check'
curl -I 'https://www.example.com/'

前三种应把Location指向https://www.example.com/test-path?from=check;第四种主站访问不应再次跳回根域名。再用浏览器打开真实存在的文章、图片和登录页面。不要只检查首页;不存在的测试路径在跳转完成后返回404是正常的路径结果,不等于跳转失败。

什么时候改成永久跳转

确认链接、登录、表单、静态资源及证书均正常后,再按站点需要将302改成301。永久跳转可能被浏览器和中间缓存保留,先使用临时跳转更容易排错。需要保留非GET请求方法的入口,应评估307或308及客户端支持;不能认为所有状态码都具有同样语义。初次切换阶段不要同时启用HSTS preload等难以快速撤销的长期策略。

循环跳转和恢复方法

  • 如果www又跳回根域名,检查应用自身的站点地址、CDN重定向及其他Nginx规则;各层必须约定同一个主域名。
  • 如果HTTPS访问反复被判成HTTP,核对代理链与应用的可信代理设置,不通过关闭证书验证处理。
  • 出现问题时恢复本次修改前的server块,检测后reload;在新浏览器会话或curl中复测,区分服务器规则与本地已缓存的301。