很多新手在给网站配置HTTPS的时候,会遇到一个问题:HTTP访问到底是做301重定向到HTTPS,还是直接配置HSTS(Strict-Transport-Security)?这两个机制看起来都能把HTTP流量引到HTTPS,它们之间有什么区别?能不能同时配置?本文就来把这件事说清楚。
先搞清楚两个机制的区别
在说配置之前,先弄明白这两个东西到底在干什么。
HTTP强制跳转(也叫HTTPS重定向),是在服务端把HTTP请求301或302跳转到HTTPS。比如访问http://example.com,浏览器收到一个响应头告诉它「去访问https://example.com」,浏览器照做,访问就过去了。整个过程浏览器是知情的——它知道自己被跳了。
HSTS不一样。它是一个响应头,叫Strict-Transport-Security。当浏览器第一次访问一个域名收到这个头之后,浏览器会把这个域名记下来。之后无论用户是敲了http://还是从第三方链接点过来,浏览器自己就自动把请求升级到HTTPS,根本不会发起HTTP请求,更不会走DNS解析后再跳转这一步。整个过程在浏览器本地完成,服务端感知不到第一次之后的HTTP流量。
一个简单对比:
- 跳转:服务端告诉浏览器该去哪
- HSTS:浏览器自己记住必须去哪
配置HTTPS强制跳转(Nginx端)
这是最常见的做法,在server块里监听80端口,然后把请求重定向到443。
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
root /var/www/html;
index index.html;
}
这里用的是301(永久重定向),告诉搜索引擎这个跳转是永久的,有助于SEO。第一次访问会慢一点(多一次HTTP往返),但之后浏览器会缓存这个跳转。
配置HSTS(Strict-Transport-Security)
HSTS的配置放在443的server块里,通过add_header指令添加到响应头中。
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# HSTS 基本配置
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
参数说明:
max-age=31536000:浏览器记住这个规则的时间,单位是秒。31536000秒等于一年。建议不要设置太短,否则意义不大。includeSubDomains:可选,表示子域名也适用这个规则。开启之前确保所有子域名都支持HTTPS。
两个机制能不能同时配置
能,而且对于大多数生产环境来说,推荐两个都配置。
原因很简单——它们服务的对象不同:
- 强制跳转:保护第一次访问的用户(浏览器还没记住HSTS规则的用户)
- HSTS:保护后续所有访问(浏览器记住之后,完全本地处理,速度更快)
两者配合使用,覆盖了从新用户第一次访问到老用户所有场景。
同时配置时的正确写法
# HTTP 监听块:做第一次跳转
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
# HTTPS 监听块
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
root /var/www/html;
index index.html;
# HSTS 配置
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 其他安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
}
常见的坑和注意点
1. 先只配跳转,不急着开HSTS
如果网站刚刚切换到HTTPS,建议先用跳转,观察一段时间确认HTTPS服务完全稳定了,再加HSTS。因为一旦浏览器记住了HSTS规则,即便你把HTTPS撤了,用户在max-age有效期内依然无法通过HTTP访问,对用户体验是灾难性的。
2. HSTS的max-age不要设太小
有些教程会写max-age=0,意思是禁用HSTS。设太小的话等于没配,浏览器记不住,下次访问还是可能走HTTP。生产环境建议至少一年(31536000秒)。
3. includeSubDomains用之前要确认
开启这个参数之前,确保所有子域名都上了HTTPS。比如api.example.com、blog.example.com这些。如果有子域名还在用HTTP,那些域名会被强制HTTPS访问,如果证书不匹配或者服务没准备好,反而会出问题。
4. 跳转别忘了带$request_uri
常见的错误写法是:
return 301 https://example.com;
这样跳转之后,用户访问的路径会被丢掉——访问http://example.com/about会跳到https://example.com而不是https://example.com/about。正确写法是带$request_uri变量。
5. 配置文件里的add_header继承问题
Nginx的add_header指令有个继承规则:在server块里定义的响应头,不会自动继承到error_page处理块。如果有自定义错误页,记得单独在error_page块里也加上add_header。
配置完怎么验证
最直接的方式是用curl检查响应头:
# 检查HSTS头是否存在
curl -I https://example.com
# 检查跳转是否生效
curl -I http://example.com
如果HSTS配置正确,会看到Strict-Transport-Security: max-age=31536000; includeSubDomains这样的响应头。HTTP重定向正确的话,访问HTTP URL会返回301/302并带Location指向HTTPS。
也可以用浏览器开发者工具的Network面板查看响应头,或者用Security Headers这类在线工具做全面检测。
总结一下
- HTTP强制跳转和HSTS是两回事,原理不同,互相补充。
- 生产环境推荐两个都配置,跳转覆盖首次访问,HSTS保护后续访问。
- 从HTTP切换到HTTPS时,先上跳转,观察稳定后再加HSTS。
- max-age设一年以上,includeSubDomains用之前确认子域名全支持HTTPS。
这两个机制配合起来,能把网站HTTPS覆盖率从「部分场景」提升到「全场景」,安全效果远好于单独用跳转。配置本身不复杂,关键是搞清楚它们的适用场景和先后顺序。
相关推荐:
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论