来自远程站点的请求到本地主机开发服务器出现CORS错误

75

周五时我的开发环境还能正常工作,但到了周一就出现问题了。在 Chrome 开发者工具控制台中,我遇到了所有资源的错误信息:

从源 'http://example.com' 访问位于 'http://localhost:8080/build/app.css' 的 CSS 样式表被 CORS 策略阻止:请求客户端未处于安全上下文且该资源位于更私密的地址空间 local

有没有什么快速解决方法?我尝试将访问控制头部设置为 access-control-allow-origin 但并没有奏效。

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

哎呀!我该如何访问我的Ardumower的ESP32 MCU Web服务器,它无法通过https提供服务,并且其Web界面通过CORS运行10.0.0.1?如果我通过HTTPS访问GUI,我会被混合内容阻止!可能应该开一个单独的问题。这里有关于新功能的更多信息:https://web.dev/cors-rfc1918-feedback/#chrome's-plans-to-enable-cors-rfc1918 - cat
8个回答

99

原始回答

我终于找到了答案,看到Chrome团队成员写的这篇关于CORS-RFC1918的RFC文档。简而言之,Chrome已经实现了CORS-RFC1918,阻止公共网络资源请求私有网络资源 - 除非公共网络资源是安全的(HTTPS)并且私有网络资源提供适当(尚未定义的)CORS头信息。

此外,您可以更改Chrome标志以暂时禁用新行为: chrome://flags/#block-insecure-private-network-requests

禁用该标志意味着您重新打开Chrome新行为旨在关闭的安全漏洞。


2021年更新:在我发布这个问题几个月后,我原始回答中提到的标志被删除了,因此我不得不通过使用HTTPS提供资产来更加令人满意地解决问题。

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

Private Network Access(以前称为CORS-RFC1918)是一个规范,禁止从较不私密的网络资源向更私密的网络资源发出请求。例如HTTP到HTTPS,或远程主机到localhost。

最终的解决方案是添加自签名证书和中间件,使得可以从我的远程开发服务器对我的本地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并选择安装证书
  2. 选择当前用户
  3. 选择将所有证书放入下列存储,然后浏览...,并选择受信任的根证书颁发机构
  4. 完成。

Firefox特定说明

默认情况下,Firefox不会尊重您的权威!请按照以下步骤进行配置:

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

1
我很想看到这个的确切规则。我也遇到了这个问题,但“私有”服务器是包括资源的Web服务器(它位于公共分配的IP块上,但不可外部路由),而资源是托管在Cloudflare上的bootstrap.js。我的理解是它应该阻止从“更私有”的端点加载的资源,我几乎看不出如何考虑couldflate在这方面更为私密。它是否考虑代理地址而不是目标的DNS解析? - Thomas Guyot-Sionnest
1
你的私有服务器是 http 还是 cloudflare https? - tvanc
1
自签名证书不是解决方案,浏览器默认不接受它们。虚拟专用网络域证书(通过互联网上某个域重新使用作为虚拟专用网络服务器)也不是解决方案,虚拟专用网络服务器有一个(非常固定、非常硬编码的)IP(只能通过VPN访问)。在浏览器中创建自己的CA更不安全,因为我必须保护这个CA密钥,这对于如此简单的问题来说是完全过度的。因此,虚拟专用网络资源必须保持http://IP。但是它仍然必须能够访问一些被保护免受滥用的定义良好的http://127.*。陷入僵局? - Tino
@musmus https://wicg.github.io/private-network-access/#headers - tvanc
@tvanc,不确定为什么你让我看这个链接,里面没有关于何时添加的信息,我有遗漏什么吗? - Musmus
显示剩余7条评论

60

忽略Chrome客户端警告并使资产可访问的方法:

1:前往chrome://flags/#block-insecure-private-network-requests

2:将Block insecure private network requests设置为Disabled

注意:仅当您在自己的计算机或开发环境中时才有效。

输入图像描述


4
2022年不再适用:/ - strix25
3
2022年9月28日,它仍在运作。 - Palanikumar
4
2-Dec-2022 -> 不工作 -> Chrome 版本:108.0.5359.72 -> 暂时解决方法 https://dev59.com/klEG5IYBdhLWcg3wZ8qh#74651311 - Palanikumar
4
2023年1月,仍在工作。 - Henrique Miranda
2023年8月28日,重新开始工作。 - Palanikumar
显示剩余2条评论

8

30
展示如何或在哪里设置此标题将使得这个答案更加有用。 - lowcrawler

2
尽管Chrome现在可以保护用户免受针对路由器和其他私有网络设备的跨站请求伪造(CSRF)攻击,但这也意味着依赖于跨站请求访问私有网络资源的合法应用程序,即企业应用程序,受到了负面影响,需要进行更改。在我们公司中,我们维护一个通过HTTPs公开暴露并调用客户端私有网络上的标签打印机上的Web服务的Web应用程序。我们最终开发了一个代理,接受公共和安全终点上的Web服务请求,并将其转发到私有网络上的Web服务。现在我们正在为他人提供此代理使用:https://p2prox.io/

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

1
刚刚遇到了这个问题,因为我们本地网络中的一个Web服务器实例也出现了同样的问题。这并不一定是一个复杂的问题。例如,如果您从公共资源(如vue.js或node.js)中包含JavaScript库,则可能会发生此情况。为了避免在本地网络中出现此问题,请在本地服务器上存储库的副本,并在您的网页中引用它。例如,使用以下方式而不是:
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.31/vue.global.min.js"></script>

使用

<script src="./lib/vue.global.min.js"></script>

1

2022年12月更新

我认为他们已经更改了标志的名称...

  • 尝试访问chrome://flags/#allow-insecure-localhost
  • 将其设置为启用
  • 重新启动Chrome浏览器

1

0

从'http://sub.domain.com/font/Sahel.css'访问CSS样式表,源自'http://sub.domain.com'的请求已被CORS策略阻止:请求客户端不是安全上下文且资源在更私有的地址空间private

我正在为我所在公司开发一个基于Web的系统,我们已经设置了DNS和域名,以便在公司内部访问该系统,并在离开公司时通过互联网访问它。从未安装过https证书。

以上引用会不时出现,并将同一域名分别指向私有级别和较不私有级别!这可以通过Ctrl + F5来解决。太荒谬了!

在我的情况下,通过在所有本地链接结尾处添加动态版本(使用?v=time()),解决了我的问题,但这会导致每次用户加载页面时都要下载所有脚本、CSS和字体!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接