Chrome 从远程站点向本地主机开发服务器请求时出现 CORS 错误

Chrome CORS error on request to localhost dev server from remote site

周五我有了一个工作的开发环境。星期一我有一个坏了。我在我所有资产的 Chrome 开发工具控制台中遇到此错误消息:

Access to CSS stylesheet at 'http://localhost:8080/build/app.css' from origin 'http://example.com' has been blocked by CORS policy: The request client is not a secure context and the resource is in more-private adress space local.

有什么快速解决方法吗?我尝试在我的 webpack devServer.headers 配置中设置 access-control-allow-origin 无济于事:

config.devServer.headers = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept'
}

原答案

我终于在这个 RFC about CORS-RFC1918 from a Chrome-team member. To sum it up, Chrome has implemented CORS-RFC1918 中找到了答案,它阻止了 public 网络资源请求 private-network 资源——除非 public-network 资源是安全的 (HTTPS) private-network 资源提供适当的 (yet-undefined) CORS headers.

还有一个 Chrome 标志,您可以更改它以暂时禁用新行为: chrome://flags/#block-insecure-private-network-requests

禁用该标志确实意味着您 re-opening Chrome 的新行为旨在关闭的安全漏洞。


2021 年更新:在我发布此问题几个月后,我在原始答案中引用的标志已被删除,而不是禁用我被迫解决的安全功能通过 HTTPS 提供资产可以更令人满意地解决这个问题。

2022 年更新:Chrome 98 已发布,引入了对 Preflight requests 的支持。根据公告,失败的请求应该产生警告并且没有其他影响,但在我的情况下,它们是破坏我的开发站点的完整错误。所以我不得不添加中间件来教 webpack-dev-server 如何处理预检请求。

Private Network Access(原CORS-RFC1918)是一种禁止从较少私有网络资源向较多私有网络资源请求的规范。就像 HTTP 到 HTTPS,或者远程主机到本地主机。

最终解决方案是添加一个 self-signed 证书和中间件,它允许从我的远程开发服务器向我的本地主机 webpack-dev-server 请求资产。

生成证书

cd path/to/.ssl
npx mkcert create-cert

配置webpack-dev-server以使用证书并提供预检请求

module.exports = {
  //...
  devServer: {
    https: {
      key: readFileSync("./.ssl/cert.key"),
      cert: readFileSync("./.ssl/cert.crt"),
      cacert: readFileSync("./.ssl/ca.crt"),
    },

    allowedHosts: ".example.dev", // should match host in origin below
    setupMiddlewares(middlewares, devServer) {
      // Serve OPTIONS requests
      devServer.app.options('*', (req, res) => {
        // Only serve if request has expected origin header
        if (/^https:\/\/example\.dev$/.test(req.headers.origin)) {
          res.set({
            "Access-Control-Allow-Credentials": "true",
            "Access-Control-Allow-Private-Network": "true",
            // Using * results in error if request includes credentials
            "Access-Control-Allow-Origin": req.headers.origin,
          })

          res.sendStatus(200)
        }
      }

      return middlewares
    }
  }
}

信任证书

  1. 在 Windows 资源管理器中右键单击 ca.crt 和 select 安装证书
  2. Select 当前用户.
  3. 选择将所有证书放入以下商店,然后浏览...,然后select 受信任的根证书颁发机构
  4. 完成。

Firefox-specific说明

默认情况下,Firefox 不会尊重您的授权!。通过以下步骤配置它:

  1. 在地址栏中输入 about:config
  2. 搜索 security.enterprise_roots.enabled
  3. 将设置切换为 true

只是一种 Chrome 忽略此警告并使资产可访问的客户端方式:

1:转到chrome://flags/#block-insecure-private-network-requests

2:将Block insecure private network requests设置为禁用

注意:当您在自己的计算机或开发环境中时,这就可以正常工作

通过将一台新服务器 header 设置为预检和常规请求,我能够允许从 localhost 到 localhost 的请求:

Access-Control-Allow-Private-Network: true

来源:
https://web.dev/cors-rfc1918-feedback/#step-2:-sending-preflight-requests-with-a-special-header

虽然 Chrome 现在保护用户免受针对路由器和专用网络上其他设备的 cross-site 请求伪造 (CSRF) 攻击是一件好事,但这也意味着合法的应用程序,即业务依赖 cross-site 对专用网络资源请求的应用程序受到负面影响,需要进行更改。在我的公司,我们维护一个 Web 应用程序,该应用程序 public 仅通过 HTTPs 公开,并在客户端专用网络上的标签打印机上调用 Web 服务。我们最终开发了一个代理,它在 public 和安全端点上接受 Web 服务请求,并将它们转发到专用网络上的 Web 服务。我们现在将此代理提供给其他人使用:https://p2prox.io/