显然,我完全误解了它的语义 . 我想到了这样的事情:
-
客户端从http:// siteA - the origin 下载javascript代码MyCode.js .
-
MyCode.js的响应头包含 Access-Control-Allow-Origin: http://siteB ,我认为这意味着允许MyCode.js对站点B进行跨源引用 .
-
客户端触发MyCode.js的一些功能,而MyCode.js又向http:// siteB发出请求,尽管是跨源请求,但这应该没问题 .
好吧,我错了 . 它根本不起作用 . 所以,我已阅读Cross-origin resource sharing并尝试阅读Cross-Origin Resource Sharing in w3c recommendation
有一件事是肯定的 - 我仍然不明白我应该如何使用这个 Headers .
我完全控制了站点A和站点B.如何启用从站点A下载的javascript代码,以使用此标头访问站点B上的资源?
附:
我不想使用JSONP .
11 回答
如果您只想测试浏览器阻止您的请求的跨域应用程序,那么您只需在不安全模式下打开浏览器并测试您的应用程序,而无需更改代码并且不会使代码不安全 . 从MAC OS,您可以从终端线执行此操作:
Access-Control-Allow-Origin
是CORS (Cross-Origin Resource Sharing) header .当站点A尝试从站点B获取内容时,站点B可以发送
Access-Control-Allow-Origin
响应标头以告知浏览器该页面的内容可由某些来源访问 . (原点是domain, plus a scheme and port number . )默认情况下,站点B的页面是not accessible to any other origin;使用Access-Control-Allow-Origin
Headers 为特定请求来源的跨域访问打开了一扇门 .对于站点B希望对站点A可访问的每个资源/页面,站点B应使用响应头为其页面提供服务:
现代浏览器不会直接阻止跨域请求 . 如果站点A从站点B请求页面,则浏览器将实际在网络级别上获取所请求的页面,并检查响应头是否将站点A列为允许的请求者域 . 如果站点B未指示允许站点A访问此页面,则浏览器将触发
XMLHttpRequest
的error
事件并拒绝响应请求的JavaScript代码的响应数据 .非简单请求
在网络级别上发生的事情可能比上面解释的稍微复杂一些 . 如果请求是"non-simple" request,则浏览器首先发送无数据"preflight" OPTIONS请求,以验证服务器是否接受请求 . 任何一个(或两个)请求都是非简单的:
使用GET或POST以外的HTTP动词(例如PUT,DELETE)
使用非简单请求标头;唯一简单的请求标头是:
Accept
Accept-Language
Content-Language
Content-Type
(当它的值为application/x-www-form-urlencoded
,multipart/form-data
或text/plain
时,这只是简单的)如果服务器响应OPTIONS预检,并且使用适当的响应标头(对于非简单动词为
Access-Control-Allow-Headers
,对于非简单动词为Access-Control-Allow-Methods
)与非简单动词和/或非简单 Headers 匹配,则浏览器发送实际请求 .假设站点A想要发送
/somePage
的PUT请求,并且非简单的Content-Type
值为application/json
,浏览器将首先发送预检请求:请注意,浏览器会自动添加
Access-Control-Request-Method
和Access-Control-Request-Headers
;你不需要添加它们 . 此OPTIONS预检获得成功的响应标头:发送实际请求时(在预检完成后),行为与处理简单请求的方式相同 . 换句话说,其预检成功的非简单请求被视为与简单请求相同(即,服务器仍必须再次发送
Access-Control-Allow-Origin
用于实际响应) .浏览器发送实际请求:
并且服务器发送回
Access-Control-Allow-Origin
,就像它对一个简单的请求一样:有关非简单请求的更多信息,请参见Understanding XMLHttpRequest over CORS .
如果您使用的是PHP,请尝试在php文件的基础上添加以下代码:
如果您使用的是localhost,请尝试以下操作:
如果您使用的是外部域,例如服务器,请尝试以下操作:
根据Same-Origin-Policy,浏览器限制安全沙箱中的客户端JavaScript,通常JS无法直接与远程通信来自不同域的服务器 . 在过去,开发人员创建了许多棘手的方法来实现跨域资源请求,最常用的方法是:
使用Flash / Silverlight或服务器端作为"proxy"与远程通信 .
带填充的JSON(JSONP) .
在iframe中嵌入远程服务器并通过fragment或window.name进行通信,请参阅here .
这些棘手的方法或多或少都有一些问题,例如JSONP可能会导致安全漏洞,如果开发人员只是“评估”它,而上面的#3,虽然它有效,但两个域应该 Build 彼此之间的严格 Contract ,它既不灵活也不优雅恕我直言:)
W3C引入了跨源资源共享(CORS)作为标准解决方案,以提供安全,灵活和推荐的标准方法来解决此问题 .
The Mechanism
从高层次我们可以简单地认为CORS是来自域A的客户端AJAX调用和域B上托管的页面之间的 Contract ,典型的跨源请求/响应将是:
DomainA AJAX request headers
DomainB response headers
我上面标记的蓝色部分是核心事实,“Origin”请求 Headers “指示跨源请求或预检请求源自的位置”,“Access-Control-Allow-Origin”响应标头指示此页面允许来自远程请求DomainA(如果值为*指示允许来自任何域的远程请求) .
正如我上面提到的,W3建议浏览器在提交实际的跨域HTTP请求之前实现“ preflight request ”,简而言之它是HTTP
OPTIONS
请求:如果foo.aspx支持OPTIONS HTTP动词,它可能会返回如下所示的响应:
仅当响应包含"Access-Control-Allow-Origin"且其值为"*"或包含提交CORS请求的域时,通过满足此mandtory条件,浏览器将提交实际的跨域请求,并将结果缓存在“ Preflight-Result-Cache ”中 .
三年前我在博客上发表了关于CORS的文章:AJAX Cross-Origin HTTP request
问题有点太老了,无法回答,但我发布此问题是为了将来对此问题的任何参考 .
根据this Mozilla开发者网络文章,
从
http://domain-a.com
提供的 HTML page 为http://domain-b.com/image.jpg
发出<img>
src请求 .今天网络上的许多页面都会从不同的域中加载 CSS stylesheets , images 和 scripts 等资源(因此应该很酷) .
同源政策
出于安全原因,浏览器会限制 cross-origin HTTP 个请求 initiated from within scripts .
例如,
XMLHttpRequest
和Fetch
遵循 same-origin policy .因此,使用
XMLHttpRequest
或Fetch
的Web应用程序只能 HTTP requests 到 its own domain .跨源资源共享(CORS)
为了改进Web应用程序,开发人员要求浏览器供应商允许跨域请求 .
Cross-Origin Resource Sharing (CORS) 机制提供Web服务器 cross-domain access controls ,它可以实现安全的跨域数据传输 .
现代浏览器在 API container 中使用 CORS (例如
XMLHttpRequest
或Fetch
)来降低跨源HTTP请求的风险 .CORS如何工作(Access-Control-Allow-Origin标头)
Wikipedia:
示例
Origin HTTP
标头发送OPTIONS
请求 .此标头的值是为父页面提供服务的域 . 当
http://www.example.com
中的页面尝试访问service.example.com
中的用户数据时,以下请求标头将发送到service.example.com
:原产地:http://www.example.com
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: *
每当我开始考虑CORS时,我对哪个站点承载 Headers 的直觉是不正确的,正如您在问题中所描述的那样 . 对我来说,考虑同一起源政策的目的是有帮助的 .
同一原始策略的目的是保护您免受siteA.com上的恶意JavaScript访问您选择仅与siteB.com共享的私人信息 . 如果没有相同的原始策略,siteA.com的作者编写的JavaScript可能会使您的浏览器使用siteB.com的身份验证cookie向siteB.com发出请求 . 通过这种方式,siteA.com可以窃取您与siteB.com共享的秘密信息 .
有时您需要跨域工作,这是CORS的用武之地.CORS放宽了domainA.com的相同原始策略,使用
Access-Control-Allow-Origin
标头列出了可信赖运行可与域A交互的JavaScript的其他域(domainB.com) .COM .要了解哪个域应该为CORS标头提供服务,请考虑这一点 . 您访问malicious.com,其中包含一些尝试向mybank.com发出跨域请求的JavaScript . 应该由mybank.com而不是malicious.com来决定它是否设置了放宽相同源策略的CORS头,允许来自malicious.com的JavaScript与之交互 . 如果malicous.com可以设置自己的CORS Headers ,允许自己的JavaScript访问mybank.com,这将完全取消相同的原始政策 .
我认为我的直觉不好的原因是我在开发网站时的观点 . 这是 my 网站,所有 my JavaScript,因此它没有做任何恶意事情,它应该由 me 指定哪些其他网站 my JavaScript可以与之交互 . 事实上,我应该考虑哪些 other 网站JavaScript试图与我的网站进行交互,我应该使用CORS来允许它们吗?
在Python中,我一直在使用Flask-CORS library取得了巨大的成功 . 它使处理CORS超级简单,无痛 . 我在下面的库文档中添加了一些代码 .
安装:
允许所有路径上所有域的CORS的简单示例:
有关更具体的示例,请参阅文档 . 我使用上面的简单示例来解决我正在构建的离子应用程序中的CORS问题,该应用程序必须访问单独的烧瓶服务器 .
对于跨源共享,请设置 Headers :
'Access-Control-Allow-Origin':'*';
Php:
header('Access-Control-Allow-Origin':'*');
节点:
app.use('Access-Control-Allow-Origin':'*');
这将允许共享不同域的内容 .
使用 React 和 Axios ,将代理链接加入URL并添加 Headers ,如下所示
https://cors-anywhere.herokuapp.com/
Your API URL
只需添加代理链接即可,但它也可以再次为无访问权限抛出错误 . 因此最好添加 Headers ,如下所示 .
1.客户端从http://siteA下载javascript代码MyCode.js - 原点 .
执行下载的代码 - 您的html脚本标记或来自javascript或其他的xhr - 来自,比方说,http://siteZ . 并且,当浏览器请求MyCode.js时,它会发送一个Origin: Headers ,说“Origin:http://siteZ”,因为它可以看到您正在请求siteA和siteZ!= siteA . (你无法阻止或干扰这一点 . )
没有 . 这意味着,只允许siteB执行此请求 . 因此,您对siteZ的MyCode.js请求会收到错误,而浏览器通常不会给您任何信息 . 但是,如果您让服务器返回A-C-A-O:siteZ,您将获得MyCode.js . 或者,如果它发送'*',那将会工作,那将让所有人进入 . 或者如果服务器总是从Origin:标头发送字符串......但是......为了安全起见,如果你害怕黑客,您的服务器应该只允许来自候选名单的来源,允许发出这些请求 .
然后,MyCode.js来自siteA . 当它向siteB发出请求时,它们都是跨域的,浏览器发送Origin:siteA,而siteB必须获取siteA,在允许的请求者的简短列表中识别它,并发送回A-C-A-O:siteA . 只有这样,浏览器才会让您的脚本获得这些请求的结果 .
我使用快递4和节点7.4和角度,我有同样的问题,我帮助这个:
a)服务器端:在文件app.js中,我给所有响应提供 Headers ,如:
this must have before all router .
我看到很多添加此 Headers :
但我不需要那个,
b)客户端:在发送ajax时需要添加:"withCredentials: true,"如:
祝好运 .