HTTP非安全源调用HTTPS接口触发CORS拦截问题排查
现有部署在非安全HTTP协议的站点host1,需要向同域下基于HTTPS部署的站点host2发起API调用,二者网络连通无访问阻断。
本地测试阶段以localhost作为host1,通过XAMPP托管网页,运行如下fetch请求时无异常,接口可成功调用,请求目标为host2提供的API接口:
fetch(url, { method: 'GET', mode: 'cors', headers: { 'Content-Type': 'application/json' }, }).then( response => { try { if(response.status == 200){ return response.json(); } reject(response.json()); } catch(error){ reject(response.text()); } }).then( data => { resolve(data); }).catch( error => { reject(error); });
在实际业务机器(非本地localhost环境)测试时触发CORS策略拦截,Chromium内核的Microsoft Edge调试工具返回报错:
Access to fetch at 'https://host2/api' from origin 'http://host1' has been blocked by CORS policy: The requesting client is not in a secure context and the resource is in a more-private address space
private.
(中文翻译:从源http://host1发起的对https://host2/api的fetch请求已被CORS策略拦截:发起请求的客户端不在安全上下文中,且请求的资源位于私密度更高的private地址空间)
Chrome浏览器下测试直接返回报错:
Failed to load resource: net::ERR_CERT_AUTHORITY_INVALID
(中文翻译:资源加载失败:网络错误,证书颁发机构无效)
本地场景和实际业务场景逻辑一致但表现不同,以下是根因定位和修复方向。
本地测试不触发拦截的核心原因是:localhost/127.0.0.1等本地回环地址被Chromium内核浏览器默认标记为可信安全上下文,哪怕承载在HTTP协议上也不会触发非安全源相关的安全校验,和实际业务机器上普通HTTP协议的host1环境有本质区别,两个报错分别对应两个独立的浏览器安全规则:
- Edge的CORS拦截报错,触发的是Chromium私有网络访问(PNA)安全规则:非安全上下文(普通HTTP站点,localhost等默认可信源除外)禁止请求地址空间私密度高于当前源的资源,当前HTTP的host1属于非安全上下文,HTTPS的host2被判定为私有地址空间资源,因此直接被拦截。
- Chrome的证书无效报错,是因为host2部署的HTTPS证书不在浏览器的默认信任链中(比如使用自签证书、内部私有CA签发的证书但未安装到业务机器的系统信任存储),浏览器在校验证书合法性阶段直接终止请求,请求根本没有到达业务接口层。
按生产环境可用性优先级排序:
- 优先方案(合规、适配所有浏览器长期规则,推荐生产使用)
- 将host1也升级为HTTPS协议部署,从根源解决非安全上下文触发PNA拦截的问题
- 为host2配置公开可信CA签发的有效SSL证书,若使用内部私有CA签发证书,需要将根证书提前部署到所有访问业务的终端机器的系统受信任根证书存储中,解决证书校验失败问题
- 在host2侧正确配置CORS响应头,将host1的HTTPS源加入
Access-Control-Allow-Origin允许列表即可,无需配置泛域名宽权限。
- 临时测试方案(仅用于本地/测试环境排错,禁止生产环境使用)
- 临时关闭PNA校验:给浏览器启动追加启动参数
--disable-features=PrivateNetworkAccessRespectPreflightResults,启动后会跳过私有网络访问的拦截规则 - 临时解决证书问题:访问host2的HTTPS地址时,在浏览器证书警告页点击「高级-继续访问」,当前浏览器会话会临时信任该证书;也可以手动把host2的证书导入到系统受信任根存储实现长期信任
- 若必须保留HTTP协议部署host1,需要在host2的所有接口(包含CORS预检请求响应)中添加响应头
Access-Control-Allow-Private-Network: true,同时配置Access-Control-Allow-Origin允许http://host1源,注意部分高版本Chromium浏览器对非安全源的该配置会默认忽略,需要配合企业浏览器策略下发才能生效。
- 临时关闭PNA校验:给浏览器启动追加启动参数
内容的提问来源于stack exchange,提问作者Kevin Minds

