HSTS配置后本地开发环境HTTPS报错怎么办?

UP主~爱琴 阅读 14

我给线上网站加了 HSTS 头,结果本地开发时用 http://localhost:3000 打不开页面了,浏览器直接报“不安全”还拒绝加载。明明本地没配 HTTPS 啊,这咋整?

我试过清除浏览器缓存和 HSTS 设置,但 Chrome 好像还是记着这个域名。有没有办法让 HSTS 只对线上生效,别影响本地开发?

我来解答 赞 8 收藏
二维码
手机扫码查看
1 条解答
公孙爱军
首先你要明白 HSTS 是什么:HTTP Strict Transport Security,就是浏览器收到这个头之后,会强制以后所有请求都走 HTTPS,哪怕你手动输入 http://localhost:3000,它也会自动重定向成 https://localhost:3000,然后本地没证书自然就报错了。

问题出在你可能把 HSTS 加在了整个域名上,比如加在了根路径或者所有请求上,导致本地开发时也被“继承”了这个策略。浏览器一旦收到 HSTS 头,哪怕你清了缓存,Chrome 还会把域名记在本地的 HSTS 列表里(存在用户配置目录里),短则几小时,长则几年(取决于 max-age),所以清除缓存没用。

解决办法有两个方向:一个是改线上 HSTS 配置,一个是本地绕过(不推荐长期用,只适合临时调试)。

先说靠谱点的方案:线上别加太狠的 HSTS 策略,尤其是 max-age 要小一点,先测试。

比如你用 nginx,别直接写成:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

这玩意儿 max-age 是秒,31536000 就是一年,浏览器死死记着你这域名要走 HTTPS。

改成这样试试:

add_header Strict-Transport-Security "max-age=600; includeSubDomains";

也就是只记 10 分钟,这样你本地调试的时候,只要等 10 分钟不访问,或者重启浏览器(有时重启会重置),HSTS 就过期了,就能用 http 回来了。

另外注意:HSTS 是按主机名生效的,localhost 和你的线上域名(比如 example.com)本来就是两个不同的 host,按理说互不影响。但如果你本地开发时用的是类似 dev.example.com 或者 test.example.com 这种子域名,而你线上给 example.com 加了 includeSubDomains,那子域名也会被强制 HTTPS,这就坑了本地开发。

所以你要检查你 HSTS 里有没有 includeSubDomains,如果本地用了子域名(比如用 docker 或者 nginx 反代 dev.example.com),就别加这个参数,或者单独给本地开发环境配置一个独立域名,比如 local.test,专门用来开发,完全不走 HSTS。

还有一个实用技巧:本地开发用 127.0.0.1 而不是 localhost。Chrome 对 localhost 的 HSTS 处理有时候更激进,而 127.0.0.1 一般不会被加进 HSTS 列表(除非你手动访问过带 HSTS 的 https://127.0.0.1:xxx)。

如果已经中招了,想立刻绕过,可以:

1. 打开 Chrome 地址栏输入:chrome://net-internals/#hsts
2. 在下面 Delete domain 栏里输入你的域名(比如 localhost 或 dev.example.com)
3. 点 Delete 按钮,立刻清除 HSTS 记录
4. 刷新页面试试

不过这个只是临时救急,下次访问带 HSTS 的 HTTPS 页面又会重新记上,所以根本还是线上别乱配。

如果你是用 Node.js(比如 Express)做反向代理或者本地开发服务器,也别在本地服务里加 HSTS 头,检查一下有没有全局 middleware 给所有响应加这个头的:

res.setHeader('Strict-Transport-Security', 'max-age=31536000');

这种删掉就完事,本地开发完全不需要。

最后提醒一句:线上上线 HSTS 前,建议先用短时间测试(比如 max-age=120),确认没问题再调大,别像我上次一样手一抖配了 1 年,结果证书快过期了,浏览器直接打不开,查了俩小时才发现是 HSTS 在捣鬼…… 真的很崩溃。
点赞
2026-02-26 05:01