xmlhttprequest无法加载无“访问控制允许来源”标头

jfewjypa  于 2021-09-13  发布在  Java
关注(0)|答案(1)|浏览(415)

tl;博士关于同一原产地政策

我有一个grunt进程,它启动一个express.js服务器示例。直到现在,它才开始提供一个空白页面,在chrome(最新版本)的开发人员控制台的错误日志中显示以下内容:
无法加载xmlhttprequesthttps://www.example.com/ 请求的资源上不存在“access control allow origin”标头。起源'http://localhost:4300因此,不允许访问。
是什么阻止我访问该页面?

byqmnocz

byqmnocz1#

tl;博士-在结尾有一个摘要,在答案中有标题,以便更容易找到相关部分。尽管如此,还是建议大家阅读所有内容,因为它为理解原因提供了有用的背景知识,使我们更容易了解如何在不同的环境中应用。

关于同一原产地政策

这是同一原产地政策。它是由浏览器实现的安全特性。
您的具体案例展示了它是如何为xmlhttprequest实现的(如果使用fetch,您将得到相同的结果),但它也适用于其他事情(例如加载到 <canvas> 或将文档加载到 <iframe> ),只是实现略有不同。
(奇怪的是,它也适用于css字体,但这是因为found Foundry坚持使用drm,而不是出于同一原产地政策通常涵盖的安全问题)。
演示sop需求的标准场景可以用三个字符来演示:
爱丽丝是一个有网络浏览器的人
鲍勃经营一个网站( https://www.[website].com/ (在你的例子中)
马洛里经营一个网站( http://localhost:4300 (在你的例子中)
alice登录到bob的网站,在那里有一些机密数据。也许是公司内部网(只能通过局域网上的浏览器访问),或者是她的网上银行(只能通过输入用户名和密码后获得的cookie访问)。
alice访问mallory的网站,该网站有一些javascript,使alice的浏览器向bob的网站发出http请求(从她的ip地址和cookies等)。这可以像使用 XMLHttpRequest 阅读 responseText .
浏览器的同源策略阻止javascript读取bob网站返回的数据(bob和alice不希望mallory访问这些数据)(请注意,例如,您可以使用 <img> 元素,因为图像的内容不暴露于javascript(或mallory)…除非您将画布放入混合中,在这种情况下,您将生成一个相同的源冲突错误)。

为什么在您认为不应该的情况下适用同一原产地政策

对于任何给定的url,都可能不需要sop。出现这种情况的两种常见情况是:
爱丽丝、鲍勃和马洛里是同一个人。
鲍勃提供的是完全公开的信息
…但浏览器无法知道上述任何一项是否正确,因此信任不是自动的,而是应用sop。在浏览器将其提供给其他网站的数据提供给其他网站之前,必须明确授予权限。

为什么同源策略只适用于网页中的javascript

浏览器扩展 * ,浏览器开发工具中的“网络”选项卡和应用程序(如postman)都是已安装的软件。他们不会仅仅因为您访问了另一个网站就将数据从一个网站传递到另一个网站的javascript。安装软件通常需要更谨慎的选择。
没有第三方(马洛里)被视为风险。 * 浏览器扩展确实需要仔细编写,以避免跨源问题。例如,请参阅chrome文档。

为什么可以在页面中显示数据而不用js读取

在许多情况下,mallory的网站会导致浏览器从第三方获取数据并显示数据(例如,通过添加 <img> 元素来显示图像)。虽然mallory的javascript无法读取该资源中的数据,但只有alice的浏览器和bob的服务器可以读取,因此它仍然是安全的。

科尔斯

这个 Access-Control-Allow-Origin 错误消息中提到的http响应头是cors标准的一部分,该标准允许bob明确授予mallory的站点通过alice的浏览器访问数据的权限。
一个基本的实施方案只包括:

Access-Control-Allow-Origin: *

…以允许任何网站读取数据。

Access-Control-Allow-Origin: http://example.com/

…将只允许特定站点访问它,bob可以根据 Origin 请求标头允许多个(但不是所有)站点访问它。
bob如何设置响应头的细节取决于bob的http服务器和/或服务器端编程语言。对于各种常见配置,有一系列指南可能会有所帮助。

注意:有些请求很复杂,在浏览器发送get/post/put/js想要发出的任何请求之前,服务器必须响应一个飞行前选项请求。仅添加 Access-Control-Allow-Origin 对特定URL的访问经常会因此而出错。
显然,通过cors授予权限是bob仅在以下情况下才会执行的操作:
这些数据不是私人的,也不是私人的
马洛里是值得信任的

但我不是鲍勃!

mallory没有标准的机制来添加此标题,因为它必须来自bob的网站,而bob不控制该网站。
如果bob正在运行一个公共api,那么可能有一种打开cors的机制(可能通过以某种方式格式化请求,或者在登录到bob站点的开发人员门户站点后使用配置选项)。不过,这必须是由bob实现的机制。mallory可以阅读bob网站上的文档,看看是否有可用的东西,或者她可以与bob交谈,让他实现cors。

提到“飞行前响应”的错误消息

一些跨源请求是预引导的。
当(粗略地说)您尝试提出跨来源请求时,会发生这种情况:
包括cookies之类的凭据
无法使用常规html表单生成(例如,具有自定义标题或无法在表单中使用的内容类型) enctype ).

如果你正确地做了一些需要飞行前准备的事情

在这些情况下,这个答案的其余部分仍然适用,但您还需要确保服务器可以侦听飞行前请求(这将是 OPTIONS (而不是 GET , POST 或者你想发送的任何信息)并以正确的方式回复 Access-Control-Allow-Origin 头,但也 Access-Control-Allow-MethodsAccess-Control-Allow-Headers 允许您使用特定的http方法或标头。

如果您错误地触发了飞行前

有时,人们在尝试构造ajax请求时会犯错误,有时这些错误会触发飞行前的需要。如果api设计为允许跨源请求,但不需要任何需要预飞行的内容,那么这可能会中断访问。
引发这种情况的常见错误包括:
试图把 Access-Control-Allow-Origin 以及请求上的其他cors响应头。这些不属于请求,也没有做任何有帮助的事情(您可以授予自己权限的权限系统有什么意义?),并且只能出现在响应上。
试图把一个 Content-Type: application/json get请求上的标头,该请求没有用于描述内容的请求正文(通常在作者混淆时) Content-TypeAccept ).
在这两种情况下,删除额外的请求头通常足以避免预飞(这将解决与支持简单请求但不支持预飞请求的API通信时的问题)。

不透明的React

有时您需要发出http请求,但不需要读取响应。e、 g.如果您正在向服务器发布日志消息以进行记录。
如果您正在使用 fetch api(而非 XMLHttpRequest ),然后您可以将其配置为不尝试使用cors。
请注意,这不会让您执行任何需要cors执行的操作。您将无法读取响应。您将无法发出需要飞行前的请求。
它将允许您发出一个简单的请求,而不会看到响应,也不会用错误消息填充开发人员控制台。
当您使用chrome发出请求时给出的chrome错误消息解释了如何执行此操作 fetch 并且未获得使用cors查看响应的权限:
在' https://example.com/ “起源” https://example.net '已被cors策略阻止:否' Access-Control-Allow-Origin '头存在于请求的资源上。如果不透明响应满足您的需要,请将请求的模式设置为“no cors”,以获取禁用cors的资源。
因此:

fetch("http://example.com", { mode: "no-cors" });

cors的替代品

jsonp

bob还可以使用类似jsonp的黑客提供数据,这是在cors出现之前人们跨源ajax的方式。
它以javascript程序的形式呈现数据,并将数据注入mallory的页面。
它要求mallory信任bob不提供恶意代码。
注意一个共同的主题:提供数据的站点必须告诉浏览器,第三方站点可以访问发送到浏览器的数据。
因为jsonp通过附加 <script> 元素以javascript程序的形式加载数据,该程序调用页面中已有的函数,尝试在返回json的url上使用jsonp技术将失败,通常会出现corb错误,因为json不是javascript。

将两个资源移动到一个原点

如果运行js的html文档和请求的url位于同一来源(共享相同的方案、主机名和端口),则默认情况下,它们的同一来源策略授予权限。不需要cors。

代理人

mallory可以使用服务器端代码获取数据(然后她可以像往常一样通过http将数据从服务器传递到alice的浏览器)。
它将:
添加cors标题
骗局

相关问题