记录开发过程中遇到的一次测试环境被强制跳转 https 的问题.

问题

背景:项目开发时有两套环境, 一个是线上 https://api.demo.example.com, 另一个是测试环境 http://test-api.demo.example.com.

某次访问无https的测试环境时,显示无响应 ERR_CONNECTION_RESET. 仔细一看,网址被跳转到了https://test-api.demo.example.com. 由于测试环境并未配置https,所以无法访问.

原因

那么为什么访问测试环境的网址会被强制跳转到 https 呢? 同时其他使用chrome的测试人员有的也会有这种问题,有的却不会跳转。

通过多次测试对比发现, 只有当访问过生产环境后才会出现测试环境被强制跳转的情况.

同时通过网上搜过强制跳转 https 机制, 发现是一个叫 HSTS 的东西在起作用。

HSTS

HTTP Strict Transport Security(通常简称为HSTS)是一个安全功能, 它告诉浏览器只能通过HTTPS访问当前资源,而不是HTTP.

其实就是一个 http response header, 语法格式如下:

Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; preload

max-age=<expire-time>
设置在浏览器收到这个请求后的<expire-time>秒的时间内凡是访问这个域名下的请求都使用HTTPS请求。

includeSubDomains 可选
如果这个可选的参数被指定,那么说明此规则也适用于该网站的所有子域名。

preload 可选
查看 预加载 HSTS 获得详情。不是标准的一部分。

查看测试环境的请求, 并未发现有 HSTS Header. 网上搜索发现可以去 chrome://net-internals/#hsts 查询跳转详情,发现确实有强制跳转.

然后突然意识到会不会是线上环境的强制跳转影响的, 于是去查看线上环境的请求, 果然发现了 HSTS Header:
strict-transport-security: max-age=15724800; includeSubDomains

image.png

而且, 其中包含了 includeSubDomains.

这样就解释了为何访问过生产环境的才会出现测试环境也强制跳转的问题: 因为测试环境被设置在生产环境的子域名下.

解决办法

原因找到了, 那么解决办法就有了,有以下几种方法可以使用:

都配置https

给不同的环境都配置https, 也就无所谓是否强制跳转了.

或者不要混用子域名

用不同的子域名

例如
生产环境用: https://api.demo.example.com
测试环境用: http://api.test-demo.example.com

用完全不同的域名

或者干脆用不同的域名, 这样也能防止一些 Cookie 信息混用

注意有些域名会被chrome强制跳转https
Chrome 于 V63 版本起会将 .dev 域名强制转换为 HTTPS

可选的域名有:

.test
.local

然后在 /etc/hosts 绑定ip到相应的测试域名地址即可.


lxz
217 声望3 粉丝