为什么会出现
Google 在 Chrome 94
版本之后开始引入 PNA(Private Network Access)
规范:禁止请求在不安全的环境(非 https)下,从公网资源访问私网资源,主要是为了防止 CSRF 攻击。
也就是说在一次请求中,就算目标资源配置了 CORS 头,但只要符合 PNA 规范,Chrome 就会判定为是一次 PNA 请求,从而产生跨域错误。
什么时候会出现
PNA 规范是什么?简单来说,就是如果在一次请求中,目标资源的 ip 比发起请求的资源的 ip 的私密等级高,那么就算这一次请求为私密请求。注意这里的判断要素是 ip
,和域名无关。
这里把目标资源分为三种类型,私密等级从低到高排序:
- 私网资源,定义为范围在
10.0.0.0/8
、172.16.0.0/12
、192.168.0.0/16
这几个 ip 段内的资源 - 本地资源,定义为
127.0.0.0/8
范围内的 ip 的资源 - 公网资源,定义为除去以上两种类型的其他所有资源
比如,在 baidu.com
资源下发起对 172.16.1.2
资源的请求,就会被 Chrome 判定为 PNA 请求。同级资源之间的请求发送则不受影响。
如何规避
从 Chrome 109
开始,PNA 资源的弃用试验结束。从此以后所有私有资源的访问都必须基于 https,基本上已经没有其他方案禁用这一规则,只能修改业务逻辑。
在我们的业务中,需要一个可以访问公网资源的电脑向局域网内的 AC 服务器 POST 镜像资源,业务逻辑如下,在 109 版本之后将不可用:
因为配置证书的流程比较麻烦,如果不想配置证书,这里可以使用另外一种方法。
在 Google 的策略中,公网资源访问本地资源,如 localhost 是不需要 https 的要求的。所以我们可以把业务流程转换为下面的步骤:
这里会新增一个本地服务用于转发来自公网资源发出的请求,这里主要需要做的额外工作是配置跨域
和 PNA 预检头
。
要注意的是,这里会额外增加一些用户成本,需要启动一个服务。
如果这个还嫌麻烦,那还有一个好方法:通过交互引导用户使用其他浏览器进行这一部分操作,比如火狐、Safari,或者低版本内核的 360、QQ 等国产 Chromium 浏览器也可以。
参考
https://developer.chrome.com/blog/private-network-access-update/