问答中心分类: JAVASCRIPT“Access-Control-Allow-Origin”标头如何工作?
0
匿名用户 提问 22分钟 前

显然,我完全误解了它的语义。我想到了这样的事情:

  1. 客户端从以下位置下载 JavaScript 代码 MyCode.jshttp://siteA起源.
  2. MyCode.js 的响应头包含访问控制允许来源:http://siteB,我认为这意味着允许 MyCode.js 对站点 B 进行跨域引用。
  3. 客户端触发 MyCode.js 的一些功能,这些功能反过来向http://siteB,这应该没问题,尽管是跨域请求。

好吧,我错了。它根本不像这样工作。所以,我读过跨域资源共享并试图阅读w3c 推荐中的跨域资源共享.
有一件事是肯定的——我仍然不明白我应该如何使用这个标题。
我可以完全控制站点 A 和站点 B。如何启用从站点 A 下载的 JavaScript 代码以使用此标头访问站点 B 上的资源?
PS:我不想使用JSONP.

pimvdb 回复 22分钟 前

我不确定,但我相信以这种方式设置标题允许站点 B 上的代码获取http://siteA/MyCode.js.

pimvdb 回复 22分钟 前

但是怎么办???为了获得标头值,必须首先获取资源,但资源是跨域的,所以浏览器不应该首先阻止请求吗?

pimvdb 回复 22分钟 前

你所描述的实际上类似于另一种做法,内容安全政策

pimvdb 回复 22分钟 前

@mark 您不必为了获取标头而获取资源。 HTTP HEADER 方法将仅返回标头。在 CORS 的情况下,使用 HTTP OPTIONS 方法完成预检检查,该方法也不返回正文。 apsillers 的回答很好地描述了这一点stackoverflow.com/posts/10636765/revisions.

pimvdb 回复 22分钟 前

@DrMcCleod 链接的wiki页面非常清楚,但是Mozilla页面……

17 Answers
0
Wayne Ye 回答 22分钟 前

跨域资源共享——CORS(AKA 跨域 AJAX 请求)是大多数 Web 开发人员可能会遇到的问题,根据 Same-Origin-Policy,浏览器将客户端 JavaScript 限制在安全沙箱中,通常 JS 无法直接与来自不同域的远程服务器通信。过去开发人员创造了许多棘手的方法来实现跨域资源请求,最常用的方法有:

  1. 使用 Flash/Silverlight 或服务器端作为“代理”与远程通信。
  2. 带填充的 JSON (JSONP)。
  3. 在 iframe 中嵌入远程服务器并通过片段或 window.name 进行通信,请参阅这里.

那些棘手的方法或多或少都有一些问题,例如如果开发人员简单地“评估”它,JSONP 可能会导致安全漏洞,以及上面的#3,虽然它有效,但两个域应该在彼此之间建立严格的契约,它既不灵活也不优雅恕我直言:)
W3C 引入了跨域资源共享 (CORS) 作为标准解决方案,以提供安全、灵活和推荐的标准方法来解决此问题。
机制
从高层次上,我们可以简单地认为 CORS 是来自域 A 的客户端 AJAX 调用与域 B 上托管的页面之间的合约,典型的跨域请求/响应将是:
DomainA AJAX 请求标头

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com

DomainB 响应标头

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

我上面标记的蓝色部分是核心事实,“Origin”请求标头“指示跨域请求或预检请求的来源”,“Access-Control-Allow-Origin”响应标头指示此页面允许远程请求来自DomainA(如果值为 * 表示允许来自任何域的远程请求)。
正如我上面提到的,W3 推荐浏览器实现一个“预检请求” 在提交实际的跨域 HTTP 请求之前,简而言之,它是一个 HTTPOPTIONS要求:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

如果 foo.aspx 支持 OPTIONS HTTP 动词,它可能会返回如下响应:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

只有当响应包含“Access-Control-Allow-Origin”且值为“*”或包含提交CORS请求的域时,满足该强制条件,浏览器才会提交实际的跨域请求,并缓存结果在 ”预检结果缓存”。
三年前,我写了一篇关于 CORS 的博客:AJAX 跨域 HTTP 请求

LuqJensen 回复 22分钟 前

这个答案让我意识到为什么我突然遇到问题而没有使用这个标头来进行 POST 和 GET 请求。我不小心直接从磁盘打开了 index.html 文件,因此客户端在 node.js 上访问的 URL 被认为是跨域的,而它只是在 localhost 上运行。通过 URL 访问(通常会这样做)“解决”了我的问题……

Si8 回复 22分钟 前

外部网络中的域能否与内部网络中的域进行通信?

Dron Bhattacharya 回复 22分钟 前

我有一个公共获取 API。但是有些人告诉启用 CORS,因为它会阻止他们的请求。我知道有一个名为 cors 的 npm 包。但我看到许多公共 API 没有启用 CORS。我还阅读了一些关于 CORS 中的安全风险的文章。我在问启用CORS会不会错.很少有人从浏览器中运行的客户端代码调用 API。任何建议都将被感激地接受。

Timo 回复 22分钟 前

我在您的最后一个链接上读到的内容:wayneye.com 目前没有任何赞助商。

Wayne Ye 回复 22分钟 前

@Timo 我将链接更新为:wayneye.me/Ajax-Cross-Origin-HTTP-request谢谢 :)

0
Peyman Mohamadpour 回答 22分钟 前

根据thisMozilla 开发者网络文章,

资源使跨域 HTTP 请求当它从与第一个资源本身服务的域或端口不同的域或端口请求资源时。

在此处输入图像描述
一个网页服务于http://domain-a.com做一个<img>src 请求http://domain-b.com/image.jpg.当今网络上的许多页面都加载资源,例如CSS 样式表,图片脚本来自不同的域(因此它应该很酷)。
同源政策
出于安全原因,浏览器限制跨域HTTP要求从脚本中启动.例如,XMLHttpRequestFetch跟着同源策略.所以,一个 Web 应用程序使用XMLHttpRequest或者Fetch只能使HTTP 请求自己的域.
跨域资源共享 (CORS)
为了改进 Web 应用程序,开发人员要求浏览器供应商允许跨域请求。
跨域资源共享 (CORS)机制提供网络服务器跨域访问控制,从而实现安全的跨域数据传输。现代浏览器在 API 容器中使用 CORS – 例如XMLHttpRequest或者Fetch– 降低跨域 HTTP 请求的风险。
CORS 的工作原理(访问控制允许来源标题)
维基百科

CORS 标准描述了新的 HTTP 标头,它为浏览器和服务器提供了一种仅在获得许可时才请求远程 URL 的方法。

虽然服务器可以执行一些验证和授权,通常是浏览器的责任支持这些标头并遵守它们施加的限制。

例子

  1. 浏览器发送OPTIONS请求Origin HTTP标题。

此标头的值是为父页面提供服务的域。当一个页面从http://www.example.com尝试访问用户的数据service.example.com,以下请求标头将被发送到service.example.com

Origin: http://www.example.com
  1. 服务器位于service.example.com可能会回应:
  • 一个Access-Control-Allow-Origin(ACAO) 响应中的标头,指示允许哪些源站点。例如:
    Access-Control-Allow-Origin: http://www.example.com
  • 如果服务器不允许跨域请求,则会出现错误页面
  • 一个Access-Control-Allow-Origin(ACAO) 标头,带有允许所有域的通配符:
    Access-Control-Allow-Origin: *
Subin Chalil 回复 22分钟 前

如何设置 none 被允许获得类似的东西Access-Control-Allow-Origin:null

Subin Chalil 回复 22分钟 前

当我不想让任何人通过 CORS 访问我的资源时,我应该设置什么值Access-Control-Allow-Origin?我的意思是否定Access-Control-Allow-Origin: *

Peyman Mohamadpour 回复 22分钟 前

只是不要设置任何东西,为此目的

Ganesan J 回复 22分钟 前

我把访问控制放在哪里

Peyman Mohamadpour 回复 22分钟 前

我你的网络服务器是 Apache,那么你可以把你的http-config或者htaccess文件

0
Dom 回答 22分钟 前

每当我开始考虑 CORS 时,我对哪个站点托管标头的直觉是不正确的,正如您在问题中所描述的那样。对我来说,考虑一下同源策略.
同源策略的目的是保护您免受 siteA.com 上的恶意 JavaScript 访问您选择仅与 siteB.com 共享的私人信息。如果没有同源策略,siteA.com 的作者编写的 JavaScript 可能会使您的浏览器使用您对 siteB.com 的身份验证 cookie 向 siteB.com 发出请求。这样,siteA.com 就可以窃取您与 siteB.com 共享的秘密信息。
有时你需要跨域工作,这就是 CORS 的用武之地。CORS 放宽了 siteB.com 的同源策略,使用Access-Control-Allow-Origin标头列出受信任运行可与 siteB.com 交互的 JavaScript 的其他域 (siteA.com)。
要了解哪个域应该为 CORS 标头提供服务,请考虑这一点。你访问恶意网站,其中包含一些尝试向mybank.com.它应该取决于mybank.com, 不是恶意网站, 来决定它是否设置放宽同源策略的 CORS 标头,允许 JavaScript 从恶意网站与它互动。如果恶意网站可以设置自己的 CORS 标头,允许自己的 JavaScript 访问mybank.com,这将完全取消同源策略。
我认为我直觉不好的原因是我在开发网站时的观点。它是我的网站,所有我的JavaScript。因此,它没有做任何恶意的事情,应该由指定哪些其他站点我的JavaScript 可以与之交互。事实上,我应该在想:哪个其他网站的 JavaScript 正在尝试与我的网站交互,我应该使用 CORS 来允许它们吗?

cellepo 回复 22分钟 前

给定第 2 段,您在第 3 段中是否有 siteA、siteB 倒退?我可能会误解,但前面的段落似乎暗示它的 siteA 正在运行有问题的 JS?

Pedro Gabriel Lima 回复 22分钟 前

来自 OP – “我认为我的直觉不好的原因是我在开发网站时的观点。这是我的网站,带有我所有的 JavaScript,因此它没有做任何恶意的事情,应该由我来指定我的 JavaScript 可以与哪些其他站点进行交互。” – 对于那些首先想到这样的人(就像我一样),还有另一条规则,不是 CORS,为此:CSP(同意安全策略) – 使用 CSP 您可以指定您的网站可以访问/到达哪个网站/网址。

0
Ben 回答 22分钟 前

根据我自己的经验,很难找到一个简单的解释,为什么 CORS 甚至是一个问题。
一旦你理解了它为什么存在,标题和讨论就会变得更加清晰。我会在几行中试一试。

这都是关于饼干的。 Cookies 按其域存储在客户端上。

一个例子:在你的电脑上,有一个 cookieyourbank.com.也许你的会话在那里。

关键:当客户端向服务器发出请求时,它将为该请求发送存储在域下的 cookie。

您已在浏览器上登录yourbank.com.您请求查看您的所有帐户,并发送 cookieyourbank.com.yourbank.com接收一堆 cookie 并发送回其响应(您的帐户)。

如果另一个客户跨原点向服务器发出请求,这些 cookie 会像以前一样一起发送。鲁罗。

你浏览到malicious.com.恶意向不同的银行发出大量请求,包括yourbank.com.

由于 cookie 按预期进行验证,服务器将授权响应。

这些饼干被收集起来并一起发送——现在,malicious.com有回应yourbank.

哎呀。

所以现在,一些问题和答案变得显而易见:

  • “我们为什么不直接阻止浏览器这样做呢?”是的。 CORS。
  • “我们如何绕过它?”让服务器告诉请求 CORS 正常。
Cameron 回复 22分钟 前

我喜欢这个答案,我觉得这是对的,但我不明白为什么看起来只有前端抛出错误,而后端可能仍在处理请求。我写了一个关于它的问题stackoverflow.com/questions/69559952/…

Ben 回复 22分钟 前

后端只能看到来自一个 URL 的一个请求。后端为yourbank.com不(明确地)知道它是malicious.com提出请求。浏览器是跟踪您访问过的所有不同域的唯一位置

Niton 回复 22分钟 前

确实允许请求通过,但发送的 cookie 始终来自请求域,这不是更有意义吗?

Ben 回复 22分钟 前

@Niton 你完全理解,他们是。问题是malicious.com可以发送请求到yourbank.com…然后收集饼干yourbank.com并发送。然后响应返回到malicious.com.

0
OsamaBinLogin 回答 22分钟 前

1. 客户端从下载 javascript 代码 MyCode.jshttp://siteA– 起源。
进行下载的代码 – 你的 html 脚本标签或来自 javascript 的 xhr 或其他 – 来自,比方说,http://siteZ.而且,当浏览器请求 MyCode.js 时,它会发送一个 Origin: 标头,上面写着“Origin:http://siteZ“,因为它可以看到您正在向 siteA 和 siteZ 请求!= siteA。(您不能停止或干涉这个。)
2. MyCode.js的响应头包含Access-Control-Allow-Origin:http://siteB,我认为这意味着允许 MyCode.js 对站点 B 进行跨域引用。
不。这意味着,仅允许 siteB 执行此请求。因此,您从 siteZ 对 MyCode.js 的请求反而会收到错误,而浏览器通常不会给您任何信息。但是如果你让你的服务器返回 ACAO: siteZ ,你会得到 MyCode.js 。或者如果它发送’*’,那会起作用,这会让每个人都进入。或者如果服务器总是从 Origin: 标头发送字符串……但是……为了安全,如果你害怕黑客,您的服务器应该只允许入围名单上的来源,允许发出这些请求。
然后,MyCode.js 来自 siteA。当它向siteB发出请求时,它们都是跨域的,浏览器发送Origin:siteA,siteB必须获取siteA,识别它在允许的请求者的短名单上,然后发回ACAO:siteA。只有这样,浏览器才会让您的脚本获得这些请求的结果。