HSTS不能用标签设置,因RFC 6797明确禁止,必须由服务器在有效HTTPS响应头中发送;在HTML解析阶段生效,已错过TLS握手后策略注册时机,浏览器直接忽略。

HSTS 不能用 标签设置,任何尝试都无效 —— 浏览器直接忽略,连调试面板里都看不到头字段。
为什么 完全没用
RFC 6797 明确禁止通过 HTML 设置 HSTS。该策略必须由服务器在**有效的 HTTPS 响应头**中发送,且证书需有效、域名匹配、未过期。HTML 解析发生在连接建立之后,而 HSTS 注册必须在 TLS 握手完成、响应头抵达的第一时间触发。 此时早已错过时机,浏览器连解析都不会解析这行。
常见错误现象:
- 页面写了
,但curl -I https://example.com输出里没有Strict-Transport-Security头 - Chrome 开发者工具 Network 面板中,HTTPS 响应的 Response Headers 里查不到该字段
- 访问
chrome://net-internals/#hsts查询域名,显示 “Not found”
Nginx / Apache 中正确添加 HSTS 响应头
HSTS 必须出现在 listen 443 ssl 的 server 块内,且**绝不能出现在 HTTP(80端口)响应中**,否则会被浏览器静默丢弃。
Nginx 示例(注意 always 参数):
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
Apache 示例(需启用 mod_headers):
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
关键点:
-
always(Nginx)或always set(Apache)不可省略,否则 301/302 响应不会携带该头 -
includeSubDomains表示子域名也受约束,加之前务必确认所有子域已支持 HTTPS -
preload是提交到浏览器预加载列表的前提,但提交前必须确保全站稳定 HTTPS 且无 HTTP 回退路径 - 不要在 HTTP server 块里加这行 —— 白加,浏览器不认
HSTS 对首次访问无效,必须搭配服务端重定向
HSTS 是“记性策略”,不是“拦截策略”。用户第一次访问 http://example.com,浏览器根本不会查 HSTS 列表,请求直接发出去,页面可能加载一半才被降级或报不安全。
所以真正起作用的组合是:
- HTTP → HTTPS 301 重定向(在 Nginx 的
listen 80块中配置) - HTTPS 响应中带
Strict-Transport-Security头(在listen 443 ssl块中)
缺一不可。只配 HSTS,首次访问仍走 HTTP;只配重定向,用户清除浏览器 HSTS 缓存后再次访问,又可能降级。
另外:max-age=0 可用于临时清除已注册的 HSTS 策略,但需确保该响应本身是 HTTPS 且被浏览器成功接收 —— 这个操作有风险,慎用。
静态 HTML 托管平台(如 GitHub Pages、Vercel)怎么开 HSTS
这些平台不提供自定义响应头入口,HSTS 默认关闭。你无法在 index.html 里写代码启用它,也不能上传配置文件。
可行路径只有两条:
- 使用支持自定义响应头的托管(如 Cloudflare Pages + Workers,或 Netlify 的
_headers文件),然后手动注入Strict-Transport-Security头 - 放弃 HSTS,改用平台自带的「强制 HTTPS」开关(如 GitHub Pages 的 Enforce HTTPS 勾选项),它本质是做 301 重定向,但不提供 HSTS 记忆能力
注意:upgrade-insecure-requests 这类 CSP meta 标签和 HSTS 完全无关,它只升级页面内资源请求,不改变主文档协议,也不能防止首次 HTTP 访问。
最容易被忽略的一点:HSTS 的 max-age 是从浏览器**首次收到该头的时间点开始倒计时**,不是从你配置完服务器那一刻起算;如果中间某次 HTTPS 响应漏发了这个头,倒计时就会中断或重置 —— 所以要确保每个 HTTPS 响应(包括 404、301)都稳定携带它。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











