朋友们,美好的一天!
我提请您注意Lydia Hallie撰写的文章“ CS Visualized:CORS”的翻译。
每个开发人员都必须处理一个错误
Access to fetched has been blocked by CORS policy
。有几种方法可以快速解决此问题。但是,让我们花些时间仔细研究一下CORS政策是什么。
我们经常需要显示其他地方的数据。在我们执行此操作之前,浏览器必须向服务器发送请求以接收此数据。
假设我们
www.mywebsite.com
要从站点上的服务器获取有关站点上用户的信息api.website.com
。
优秀的!我们刚刚向服务器发送了一个请求,并收到了JSON数据作为响应。
现在,让我们尝试将类似的请求发送到另一个域。而不是发送一个请求,让我们
www.mywebsite.com
与发送www.anotherdomain.com
。
发生了什么?我们发送了完全相同的请求,但是这次浏览器显示了某种错误。
我们看到CORS发挥了作用。为什么会发生此错误,这是什么意思?
共同来源政策
网络上有一种叫做“通用原产地政策”(以下简称POP)的东西。默认情况下,我们只能访问与请求源相同的资源。例如,我们可以加载位于中的图像
https://mywebsite.com/image1.png
。
当源位于不同的(子)域,协议或端口中时,源就不同。
很酷,但是为什么需要POP?
假设它不存在,并且您不小心单击了姨妈在Facebook上发布的病毒链接。此链接将您重定向到具有嵌入式iframe的“恶意网站”,该iframe会加载您的银行网站并使用Cookie成功登录该网站。
“邪恶网站”的开发人员确保他可以访问iframe,并且可以与您银行网站DOM的内容进行交互,以代表您将资金转入他的帐户。
是的...这是一个严重的安全问题。我们不希望任何人在我们不知情的情况下接触任何东西。
幸运的是,EPP存在。此策略限制从其他来源访问资源。
在这种情况下,源
www.evilwebsite.com
尝试从source访问资源www.bank.com
。EPP会阻止此访问,并禁止不良站点开发人员访问您的银行数据。
好的,但是...如何运作?
客户端CORS
即使EPP仅适用于脚本,浏览器也会将其“扩展”到任何JavaScript请求:默认情况下,我们只能从一个来源访问资源。
嗯,但是……我们经常需要从另一个来源获取资源。也许我们的前端需要使用服务器API来加载数据。为了安全地从其他来源检索资源,浏览器实现了一种称为CORS的机制。
CORS代表跨域资源共享。虽然浏览器禁止其他来源的资源,但我们可以使用CORS更改此限制,同时保持安全。
用户代理(浏览器)可以使用CORS允许跨域请求,否则将根据某些HTTP响应标头阻止跨域请求。
当对另一个源发出请求时,客户端会自动向HTTP request添加标头
Origin
。此标头的值是请求的来源。
为了使浏览器允许从其他来源检索资源,服务器的响应还必须包含特定的标头。
服务器端CORS
作为后端开发人员,我们可以通过包含以开头的自定义标头,允许其他来源获取资源
Access-Control-*
。基于此类标头的值,浏览器允许资源共享。
有几个CORS标头,但必须是其中之一:
Access-Control-Allow-Origin
。
此标头的含义决定了我们的资源可以接收哪些资源。
如果我们正在开发需要访问的服务器
https://mywebsite.com
,则必须将此域添加到头文件中Access-Control-Allow-Origin
。
大。现在,此标头已添加到发送给客户端的服务器响应中。 EPP不再阻止我们
https://api.mywebsite.com
通过发送来自的请求来接收资源https://mywebsite.com
。
浏览器的CORS机制检查响应
Access-Control-Allow-Origin
标头和请求标头的值是否匹配Origin
。
在这种情况下,请求的源是
https://www.mywebsite.com
list中指定的响应头Access-Control-Allow-Origin
。
优秀的。现在我们可以从其他来源获取资源。如果我们尝试从未列出的来源进行此操作,会发生什么
Access-Control-Allow-Origin
?
是的,CORS阻止了对资源的访问。
The 'Access-Control-Allow-Origin' header has a value
'https://www.mywebsite.com' that is not equal
to the supplied origin.
在这种情况下,源
https://www.anotherwebsite.com
未在中列出Access-Control-Allow-Origin
。 CORS已成功拒绝请求的数据。
CORS允许您将
*
允许的来源指定为值。这意味着资源将可用于任何来源,因此请小心。
Access-Control-Allow-Origin
是我们可以设置的众多标题之一。后端开发人员可以将CORS配置为允许(拒绝)特定请求。
另一个常见的标题是
Access-Control-Allow-Methods
。 CORS仅允许使用指定方法发送的来自其他来源的请求。
在这种情况下,仅允许使用GET,POST或PUT方法发送的请求。其他方法如PATCH或DELETE将被阻止。
对于使用PUT,PATCH和DELETE方法发送的请求,CORS以特殊的方式对待它们。这些“棘手”查询有时被称为飞行前查询。
初步要求
CORS处理两种类型的请求:简单请求和临时请求。查询的内容取决于其某些值。
如果使用GET或POST方法发送请求并且不包含其他标头,则该请求很简单。其他任何请求都是初步的。
好的,但是预请求是什么意思,为什么需要这样的请求?
在发送实际请求之前,客户端会向服务器发送一个初步请求,其中包含有关实际请求的信息:有关其方法,附加标头(包括
Access-Control-Request-*
等)的信息。
服务器接收临时请求,并发送包含CORS标头的空临时响应。浏览器会收到一个临时响应,并检查是否允许实际的请求。
如果是这样,则浏览器发送实际的请求并作为响应接收数据。
否则,CORS将阻止预请求,并且不会发送实际请求。预先请求是防止在服务器上访问和修改资源的好方法。这样可以保护服务器免受其他来源的潜在有害请求。
为了减少重复请求的数量,我们可以通过
Access-Control-Max-Age
在CORS请求中添加标头来缓存临时响应。这样避免了重新发送初步请求。
证书
默认情况下,仅针对来自单一来源的请求安装Cookie,授权标头和TLS证书。但是,我们可能需要在其他来源的请求中使用这些权限。也许我们希望在请求中包含cookie,以便服务器可以用来标识用户。
尽管CORS默认情况下不包含权限,但我们可以使用header更改它
Access-Control-Allow-Credentials
。
如果我们想在来自其他来源的请求中包含cookie和其他授权标头,则需要将字段设置为请求中的
withCredentials
值true
,并将标头添加Access-Control-Allow-Credentials
到响应中。
完成后,现在我们可以在来自其他来源的请求中包含凭据。
希望本文对您有所帮助。感谢您的关注。