文章目录
HSTS失效,先别急着把 max-age 改大。更有效的排查顺序是:确认 HTTPS 本身正常,检查 HTTP 永久重定向,再核对 HTTPS 响应头、域名覆盖范围和浏览器保存的策略。HSTS依赖安全连接,也受浏览器本地策略影响;配置文件里写过响应头,不代表用户已经收到并记住了它。[1]
一、HTTP、HTTPS 和 HSTS 分别负责什么
HTTPS提供加密传输。HTTP 到 HTTPS 的 301 或 308 重定向,是服务器收到旧网址请求后,告诉客户端新地址在哪里;HSTS(HTTP严格传输安全)则让浏览器记住某个域名只能使用 HTTPS,在后续 HTTP 请求发出前升级协议。[1][4]
因此,证书、服务器重定向和 HSTS 要分别检查。浏览器能够自动打开 HTTPS,不等于服务器的 HTTP 入口已经配置正确。
二、先修好 HTTPS,再检查 HTTP 跳转
先直接访问正式域名的 HTTPS 地址。证书过期、域名不匹配或 TLS 连接错误,都应先解决。HSTS要求浏览器在安全连接出错时停止访问,而不是替网站消除证书错误。[1][2]
接着检查旧 HTTP 地址是否通过 301 或 308 跳到对应的 HTTPS 地址,尽量直接到最终规范网址。旧文章应对应新文章,不要把大量旧网址统一导向不相关的首页。[4]
以下是排查命令示例,请将 www.example.com 替换为需要检查的域名:
# 检查 HTTP 状态码与 Location
curl -sS -D - -o /dev/null http://www.example.com/
# 检查 HTTPS 连接与响应头
curl -sS -D - -o /dev/null https://www.example.com/
对 HTTP 响应,重点看状态码和 Location;对 HTTPS 响应,确认连接验证通过,再查 Strict-Transport-Security。这两条命令不自动跟随重定向,如果仍有跳转,要沿目标地址继续检查。
不要用 -k 跳过证书校验,再把请求成功当作 HTTPS 正常的证明。
三、HSTS必须出现在实际的 HTTPS 响应头里
浏览器会忽略通过 HTTP 返回的 HSTS 头。网页里的文字或 meta 标签,也不能代替标准的 Strict-Transport-Security 响应头。[1][2]
检查参数时,max-age 必须是以秒为单位的非负整数,不能写成 max-age=300s;max-age=0 则表示停用当前主机的动态 HSTS 策略。[2]
如果使用 Nginx,可以先在已经配置好证书的 HTTPS server 块内测试:
# 短期测试示例,不是完整的生产部署配置
add_header Strict-Transport-Security "max-age=300" always;
这个示例先对当前主机设置短期策略,没有启用子域覆盖或预加载。确认 HTTPS、证书续期和相关访问路径稳定后,再逐步延长有效期。[1][5]
Nginx默认只对特定状态码添加响应头,always 可以取消该状态码限制。如果某个 location 另外定义了 add_header,在默认继承规则下,上层的 HSTS 头可能不再继承。因此,部署后不能只检查首页,还应检查内页及异常响应。[3]
使用 CDN 或反向代理时,应检查用户访问公开域名实际收到的响应头,而不是仅看源站配置。如果 HTTPS 入口还会重定向,也应检查这一响应,不能只看最终页面。[5]
同时避免多个节点重复添加冲突的 HSTS 头:RFC 6797 要求浏览器面对多个同名 HSTS 响应头时,只处理第一条。[2]
四、几种容易被误判为“HSTS失效”的现象
首次访问 HTTP,仍然出现服务器跳转
浏览器如果尚未获得适用的 HSTS 策略,第一次 HTTP 访问可能仍走服务器重定向,随后才通过 HTTPS 响应学习策略。这不一定代表配置失效;常规 HSTS 本来就需要浏览器先收到一次有效的 HTTPS 响应头。[1]
www 生效,裸域或其他子域不生效
www.example.com 的策略不会自动覆盖 example.com 或 api.example.com。父域设置 includeSubDomains 可以覆盖子域,但浏览器需要先获得这一父域策略;用户直接访问的子域也应自行返回 HSTS 头。[1]
启用 includeSubDomains 前,要确认覆盖范围内提供网页或 HTTP API 的子域都能提供正常 HTTPS,包括内部使用的子域。否则,强制升级协议可能让原本仅支持 HTTP 的服务无法访问。[5]
测试也要使用正确域名。IP地址不能被记录为 HSTS 主机,用源站 IP 访问不能替代域名测试。[1]
删除响应头后,浏览器仍然强制 HTTPS
浏览器已经保存的策略,在到期前仍会继续生效。服务器不再输出 HSTS 头,不会让已有策略立即消失;每次收到有效响应头,浏览器还会更新策略的到期时间。[1]
另外,地址栏变成 HTTPS 也可能来自服务器跳转或浏览器自身的自动升级行为。仅观察地址栏,无法区分这些机制。[1][5]
五、需要回滚时,不能只删除配置
对浏览器从响应头学习到的 HSTS 策略,需要通过有效的 HTTPS 连接返回:
Strict-Transport-Security: max-age=0
浏览器收到后,才会删除当前主机的动态策略。通过 HTTP 返回这个头无效,删除父域策略也不会一并删除子域独立保存的策略。[1]
如果仍有父域的 includeSubDomains 策略,或域名已经进入预加载名单,单独设置 max-age=0 不能解除所有强制 HTTPS 行为。[1][5]
预加载名单需要按相应服务流程申请移除,再等待变更传播到浏览器,不能靠删掉响应头里的 preload 立即撤销。HSTS预加载提交站目前明确建议使用 HSTS,但不推荐普遍使用 HSTS 预加载。因此,不要把 preload 当作普通网站上线时必须勾选的选项,更不要为了 SEO 盲目开启。[5]
如果证书已经出错,应优先恢复有效的 HTTPS 服务,再处理策略回滚,而不是要求访客绕过安全警告。
六、SEO技术诊断还要核对网址迁移
解决 HSTS 问题后,HTTPS 迁移的 SEO 检查仍需单独完成。按照 Google 的站点迁移指南,重点核对:
- 旧网址通过服务器端 301 或 308 指向相关的新网址,避免不必要的跳转链。[4]
canonical、站内链接和sitemap使用一致、正确的规范 HTTPS 地址。[4]- 需要被索引的页面没有遗留开发阶段的
noindex或robots.txt限制。[4] - 迁移后检查抓取错误、异常 404,以及服务器访问和错误日志。[4]
这些是 Google 的迁移建议,不能直接当作百度、360 或搜狗的排名规则。其他搜索引擎的抓取与索引情况,应结合各自的官方工具和实际反馈核验。
HTTPS连接正常、HSTS生效,不能证明页面已经被搜索引擎收录。诊断时要分别验证:HTTPS连接是否有效,旧网址是否跳到正确页面,浏览器是否获得适用的 HSTS 策略,搜索引擎是否能抓取并识别规范网址。
Sources
[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Strict-Transport-Security — Strict-Transport-Security header - HTTP | MDN
[2] https://www.rfc-editor.org/rfc/rfc6797.txt
[3] https://nginx.org/en/docs/http/ngx_http_headers_module.html — Module ngx_http_headers_module
[4] https://developers.google.com/search/docs/crawling-indexing/site-move-with-url-changes?hl=en — Site Moves and Migrations | Google Search Central | Documentation | Google for Developers
[5] https://hstspreload.org — HSTS Preload List Submission