目录
什么是HSTS预加载列表
HSTS Preload List是由各大浏览器厂商维护的一组域名清单。一旦你的域名被加入这个列表,浏览器会直接通过HTTPS访问你的网站,即使用户在地址栏输入的是http://。这意味着你的域名从根本上杜绝了HTTP明文访问的可能性。
目前主流浏览器(Chrome、Firefox、Edge、Safari)都内置了这个列表。提交入口是 hstspreload.org,提交后通常需要数周到数月才能在所有浏览器中生效。
但很多站长在提交时遇到了各种报错,导致提交被拒。这篇文章把最常见的原因总结出来,帮你一次性排查到位。
提交HSTS预加载的前提条件
在提交之前,你的HSTS响应头必须满足以下全部条件:
- max-age 至少
31536000秒(一年) - 包含
includeSubDomains指令 - 包含
preload指令 - 响应头必须通过HTTPS返回(HTTP响应头会被忽略)
- 根域名和
www子域名都必须正确返回HSTS头
正确的HSTS响应头示例:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
以上任何一条不满足,提交都会失败。下面具体看失败的原因。
提交失败的7个常见原因
1. max-age值不够大
这是最基础的错误。HSTS预加载列表要求 max-age 至少为 31536000(1年)。如果你设置了较短的时间用于测试(比如 max-age=300),测试完忘记改回来,提交就会直接被拒。
解决办法:确认生产环境的 max-age 不小于 31536000。如果之前用了短值做测试,改回来后需要等待一段时间再提交。
2. 缺少 includeSubDomains 指令
预加载列表要求你的HSTS策略覆盖所有子域名,因此 includeSubDomains 是必选项,不是可选项。
缺少这个指令时,hstspreload.org会提示 "HSTS header does not contain includeSubDomains"。
解决办法:在Nginx配置中加上 includeSubDomains:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
3. 缺少 preload 指令
这个容易被忽略。你想加入预加载列表,就必须显式声明 preload。浏览器厂商认为这应该是一个深思熟虑的决定,所以需要你主动声明"我确实要加入预加载"。
解决办法:在HSTS头的末尾加上 preload,注意用分号分隔。
4. HTTP页面也返回了HSTS头
这是一个很隐蔽的问题。如果HTTP页面(非HTTPS)也返回了HSTS响应头,提交会被拒绝。HSTS头应该只在HTTPS响应中返回。
在Nginx中,这个问题通常出现在同时监听80和443端口的server块中,80端口的location也继承了 add_header 指令。
解决办法:确保80端口只做重定向,不输出HSTS头:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com www.example.com;
# HSTS头只在这里设置
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}
5. www子域名未正确配置HSTS
预加载列表提交时会检查根域名和 www 子域名。如果 www.example.com 没有返回正确的HSTS头,或者指向了不同的服务器且那台服务器没有配置HSTS,提交就会失败。
解决办法:确保根域名和www子域名都:
- 启用了HTTPS
- 返回了完整的HSTS头(包含三个必填指令)
- HTTP请求正确重定向到HTTPS
6. HSTS头被重复设置或被覆盖
Nginx的 add_header 指令有一个容易踩的坑:如果子级location块中也使用了 add_header,父级的 add_header 指令会被完全覆盖,而不是追加。
比如你在server块设了HSTS头,但在某个location里设了CSP头,结果那个location返回的响应里HSTS头就没了。
解决办法:使用 always 参数,并检查是否在子级location中覆盖了header。更推荐的方式是使用 headers-more-nginx-module 模块,它不受继承规则限制。
7. 链式重定向导致HSTS头丢失
如果你的域名经过了多次重定向(比如 http:// → https:// → https://www.),中间的某一次重定向跳转可能导致最终页面的HSTS头没有被浏览器接收到。
这种情况在Cloudflare等CDN与源站混用的场景中很常见。
解决办法:简化重定向链,尽量做到一步到位。避免 HTTP → HTTPS → www 三步跳转,直接合并为两步或一步。
提交失败后的排查步骤
按照以下顺序逐一排查,能覆盖90%以上的失败原因:
- 用curl验证HSTS头:对根域名和www子域名分别执行
curl -sI https://你的域名,检查响应头中是否包含完整的HSTS头 - 检查HTTP响应:执行
curl -sI http://你的域名,确认HTTP页面不返回HSTS头 - 在线检测:访问 hstspreload.org,在 "Domain" 框中输入域名,点击 "Check status" 查看详细检测结果
- 检查所有子域名:如果有重要的子域名(如API、管理后台),确认它们也能正常使用HTTPS
- 清除浏览器缓存后重试:有时候检测结果会被缓存,等几分钟再提交
成功提交后的注意事项
- 提交后不可轻易撤销:从预加载列表移除需要很长时间(Chrome约30-70周,Firefox约52周),务必在提交前充分测试
- 必须持续维护HTTPS:一旦加入预加载列表,如果HTTPS证书过期或服务器无法通过HTTPS访问,用户将完全无法访问你的网站
- 关注CDN配置:使用CDN时,确保CDN也正确转发了HSTS头,否则源站的配置在CDN层面会被覆盖
- 定期检查状态:在 hstspreload.org 上定期查询域名状态,确认预加载是否已生效
相关文章推荐
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论