最稳妥的方式是用return 301指令单独监听80端口实现HTTP全站跳转至HTTPS,同时确保443端口独立配置SSL证书、TLS协议及HSTS头,并在代理场景下补充error_page 497处理。

最稳妥的方式是用 return 301 指令单独监听 80 端口,把所有 HTTP 请求原路跳转到 HTTPS,同时确保 443 端口的 HTTPS 服务已完整就绪——跳转只是引导,加密靠的是后端真正可用的 SSL 配置。
只用一个 return 301 实现全站跳转
在 Nginx 配置中新增一个纯 HTTP 的 server 块,不写任何 SSL 相关指令,只做一件事:收请求、发 301、跳走。
- 必须写
listen 80;,明确绑定 HTTP 流量入口 - 推荐用
return 301 https://$host$request_uri;:
—$host取请求头里的域名(支持 www 和非 www、多域名),比硬编码更灵活
—$request_uri自动包含路径和全部查询参数(如/login?next=/admin),不会丢参 - 不要用
rewrite替代return,后者无正则解析开销,响应更快、逻辑更干净
HTTPS server 必须独立且能正常响应
跳过去没人接,用户就会看到“连接失败”或证书错误。所以另一个 server 块必须真实提供加密服务。
- 监听
443 ssl http2;(http2 可选但建议开启) -
ssl_certificate和ssl_certificate_key路径要绝对准确,私钥权限设为600 - 启用现代 TLS 协议:
ssl_protocols TLSv1.2 TLSv1.3; - 加上 HSTS 头:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;,让浏览器记住只走 HTTPS
注意代理或 CDN 场景下的特殊处理
如果 Nginx 前面有 Cloudflare、ALB 或 Traefik 这类 HTTPS 终结代理,用户发的是 HTTPS,但代理以 HTTP 转发给 Nginx,此时 80 端口跳转会失效。
- 在 443 server 块里加一句:
error_page 497 =301 https://$host$request_uri;
— 497 是 Nginx 内部状态码,表示“收到 HTTP 请求但配置了 SSL”,可捕获代理误传的 HTTP 流量 - 代理需透传
X-Forwarded-Proto: https,Nginx 才能识别原始协议 - 若代理 Header 含下划线(如
X-Forwarded-For),需在 http 块开头加underscores_in_headers on;
验证跳转是否真正“完美”
改完配置不能只看是否跳了,关键看跳得准不准、稳不稳。
- 先运行
nginx -t,确认语法正确、证书路径可读、权限无误 - 再执行
nginx -s reload生效,不要重启整个服务 - 用
curl -I http://example.com/test?a=1检查:
— 状态码必须是301 Moved Permanently(不是 302)
—Location响应头必须是https://example.com/test?a=1,路径和参数零丢失 - 浏览器访问 HTTP 地址,地址栏应秒变 HTTPS 并显示锁图标,无混合内容警告


















