全站强制安全传输需http 301跳转与https hsts响应头协同:80端口server块用return 301跳转,443端口server块配add_header strict-transport-security "max-age=31536000; includesubdomains; preload" always;。

要让全站真正实现强制安全传输,关键不是只做跳转,而是让浏览器从第一次访问起就拒绝 HTTP 请求。Nginx 本身不能“拦截”用户手动输入的 http://,但可以通过两层机制协同达成效果:HTTP 请求进来时立即 301 跳转到 HTTPS;HTTPS 响应中携带 HSTS 头,告诉浏览器“之后所有对该域名的请求,必须自动改用 HTTPS”。这两步缺一不可。
配置 80 端口无条件跳转
这是用户访问 http:// 时的第一道防线,必须干净、高效、不丢失原始路径:
- 单独写一个
server块,监听80端口,不要和 HTTPS 的配置混在一起 - 使用
return 301 https://$host$request_uri;,比rewrite更轻量、无正则开销、不会意外触发循环 -
server_name必须包含你实际使用的全部域名(如example.com www.example.com),否则部分请求可能无法匹配而返回 404 或走错 server - 确保该块中不包含
ssl相关指令,也不加载证书——80 端口只负责跳转,不处理加密
配置 443 端口并启用 HSTS
只有 HTTPS 服务稳定运行,跳转才有意义;而只有启用 HSTS,才能堵住首次访问时的明文漏洞:
- 在监听
443 ssl http2的server块中,确认ssl_certificate和ssl_certificate_key指向正确路径(Linux 推荐绝对路径,如/etc/nginx/ssl/example.com.crt) - 禁用老旧协议:
ssl_protocols TLSv1.2 TLSv1.3;,不保留 TLSv1.1 及以下版本 - 添加 HSTS 响应头:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; -
max-age=31536000表示一年内浏览器将强制 HTTPS;includeSubDomains扩展策略到所有子域名;preload是为提交至浏览器预加载列表准备的,加了就不能轻易撤回
验证与注意事项
配置完成后,需验证是否真正生效,而非仅看跳转是否成功:
- 用 curl 测试跳转:
curl -I http://example.com应返回301 Moved Permanently且Location头完整准确 - 访问 HTTPS 页面后,检查响应头是否含
Strict-Transport-Security,可用浏览器开发者工具的 Network 面板查看 - 私钥文件权限必须是
600,属主为 Nginx 运行用户(如nginx或www-data),否则启动会报错 - 若使用 Let’s Encrypt,记得配置自动续期,并在续期后重载 Nginx(
nginx -s reload),避免证书过期导致 HTTPS 中断











