文章

HSTS 缓存(307 跳转) 的处理

HSTS 缓存(307 跳转) 的处理

背景

最近遇到使用HTTP访问自托管的Harbor某个域名时Chrome自动返回307,并重定向到HTTPS, 但是由于证书过期导致无法访问, 错误提示类似下图:

错误示例

表现行为:

  • 无法通过访问HTTP访问, 指定协议也会跳转到HTTPS
  • 同时提示证书错误,导致页面无法加载
  • 更换游览器或者使用无痕模式能使用HTTP访问, 且正常(在服务允许HTTP访问的情况下)

原理分析

这个特性是由现代浏览器和服务器的 HSTS(HTTP Strict Transport Security) 功能导致

即自动将不安全的 HTTP 请求使用 307 Internal Redirect 跳转到 HTTPS 请求。这是由Chrome内部HSTS缓存导致的。首次访问一个设置了HSTS的网站,浏览器会接收并在当前隐身会话期间记住这个HSTS策略, 也就是说HSTS只要在理论上的第一次访问后,后来就不经网页服务器返回,浏览器会查询本地数据,直接使用 HSTS 307 跳转到安全的 HTTPS,以此来加强网络访问的安全性。

HSTS机制详情参考 HSTS机制详解

在安全层面这的确是个很先进的功能,但对开发环境耐受就带来了麻烦,一旦网页服务器设置了 HSTS,且在理论上的第一次无意或有意访问过,这就被浏览器缓存住了。此后,浏览器自行决定将不会再访问该域的 HTTP了,哪怕服务端已经修改了相关配置。

在HTTP/1.1中,新增了303 See Other、307 Temporary Redirect这两个状态码,这两个状态码和301、302状态码有什么区别呢?

  1. 对于301302location中包含的重定向url,如果请求method不是GET或者HEAD,那么浏览器是禁止自动重定向的,除非得到用户的确认,因为POSTPUT等请求是非冥等的(也就是再次请求时服务器的资源可能已经发生了变化)。
  2. 虽然rfc明确了上述的规定,但是很多的浏览器不遵守这条规定,无论原来的请求方法是什么都会自动用GET方法重定向到location指定的url。就是说现存的很多浏览器在遇到POST请求返回301302状态码的时候自动用GET请求location中的url,无需用户确认。
  3. HTTP 1.1中新增了303307状态码,用来明确服务器期待客户端进行何种反应。
  4. 303状态码其实就是上面301302状态码的”不合法”动作,指示客户端可以自动用GET方法重定向请求location中的url,无需用户确认。也就是把前面301302状态码的处理动作”合法化”了。
  5. 307状态码就是301302原本需要遵守的规定,除GETHEAD方法外,其他的请求方法必须等客户确认才能跳转。
  6. 303307其实就是把原来301302不”合法”的处理动作给”合法化”,因为发现大家都不太遵守,所以干脆就增加一条规定。

MDN Web 文档:

解决方案

在Chrome地址栏打开, 手动清除HSTS缓存即可

1
chrome://net-internals/#hsts

如果是Edge游览器访问:

1
edge://net-internals/#hsts

chrome HSTS 管理

Domain Security Policy -> Delete domain security policies 选型中数量要清除HSTS缓存的域名, 点击Delete删除即可

如果一个网站被列入了Chrome的HSTS Preload List,那么无论是正常模式还是隐身模式,浏览器在首次访问该网站时都会直接使用HTTPS,因为这个策略是硬编码在浏览器内部的,不依赖于本地缓存。

参考

本文由作者按照 CC BY 4.0 进行授权