申请到 SSL 证书之后,还需要把所有 HTTP 流量强制跳转到 HTTPS,并配置 HSTS 头部,否则用户直接输入 http:// 还是会走明文通道。本文讲清 Nginx 中 301 跳转的写法、HSTS 配置以及如何排查混合内容问题。
本文要点
- 用 Nginx
return 301强制 HTTP 跳转到 HTTPS - HSTS 头部的作用、写法与 preload 注意事项
- 什么是混合内容,如何定位与修复
- 验证跳转与安全头部是否生效
为什么仅有证书还不够
Let's Encrypt 证书只让 443 端口可以跑 HTTPS,但 80 端口的 HTTP 服务默认仍然存在。如果用户手动输入 http://example.com 或点击旧的 HTTP 链接,还是会走不加密的连接。必须明确配置 301 跳转,强制所有流量走 HTTPS。
Nginx 301 跳转配置
在 Nginx 配置中添加一个专门监听 80 端口的 server 块,把所有 HTTP 请求重定向到 HTTPS:
# HTTP → HTTPS 强制跳转
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
# 永久重定向到 HTTPS(301)
return 301 https://$host$request_uri;
}
# HTTPS 主站配置
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/example;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}301 vs 302
301(永久重定向)而非 302(临时重定向)。301 会被浏览器缓存,下次直接走 HTTPS,减少一次 RTT;而且对 SEO 也更友好。配置 HSTS
HSTS(HTTP Strict Transport Security)告诉浏览器:在 max-age 指定的时间内,对该域名的所有请求都直接走 HTTPS,不需要先发 HTTP 再重定向,彻底消除那次跳转的窗口期。
# 在 HTTPS server 块内的 location / 或 server 级别添加:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;| 参数 | 含义 | 建议值 |
|---|---|---|
| max-age | 强制 HTTPS 的时长(秒) | 31536000(1 年) |
| includeSubDomains | 对所有子域名同样生效 | 根据需要添加 |
| preload | 申请加入浏览器内置 HSTS 列表 | 谨慎使用,撤销成本极高 |
preload 慎用
SSL 协议与加密套件优化
在 HTTPS 块内补充以下配置,禁用旧版不安全协议:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;混合内容问题
什么是混合内容
HTTPS 页面中通过 HTTP 加载图片、JS、CSS 等资源,称为混合内容(Mixed Content)。浏览器会警告甚至拦截,导致样式丢失或脚本不执行。
如何定位
- 打开浏览器开发者工具(F12)
- 切换到 Console 标签,查找 Mixed Content 警告
- 或在 Network 标签中筛选
http://开头的资源
如何修复
- 把页面中所有 HTTP 链接改为 HTTPS 或协议相对路径(
//example.com/style.css) - 在 Nginx 中添加 CSP 升级头:
add_header Content-Security-Policy "upgrade-insecure-requests";
验证跳转与安全头
# 验证 301 跳转
curl -I http://example.com
# 应看到 HTTP/1.1 301 Moved Permanently 和 Location: https://...
# 验证 HTTPS 响应头
curl -I https://example.com
# 应看到 Strict-Transport-Security 头推荐在线检测工具
小结
- 80 端口 server 块用
return 301 https://做永久跳转 - HTTPS 块内加 HSTS 头,让浏览器记住强制走 HTTPS
- 禁用 TLS 1.0/1.1,只保留 1.2 和 1.3
- 用 curl -I 和 SSL Labs 验证配置效果
常见问题
配置跳转后网站出现重定向循环怎么办?
通常是 Cloudflare 等 CDN 的 SSL 模式设置为「灵活」,导致 CDN→源站走 HTTP 又被跳转。把 CDN 的 SSL 模式改为「完全」或「完全(严格)」即可解决。
HSTS 设置后能取消吗?
可以删除响应头,但浏览器需等待 max-age 过期才会停止强制 HTTPS。若设置了 preload,还需要向各浏览器提交移除申请,周期较长。
return 301 和 rewrite 哪个更好?
推荐 return 301,写法简洁、性能更好,Nginx 不需要执行正则匹配就能直接返回响应。