共同来源政策和CORS:视觉指南





朋友们,美好的一天!



我提请您注意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.comEPP会阻止此访问,并禁止不良站点开发人员访问您的银行数据。



好的,但是...如何运作?



客户端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.comlist中指定的响应头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和其他授权标头,则需要将字段设置为请求中withCredentialstrue,并将标头添加Access-Control-Allow-Credentials到响应中。







完成后,现在我们可以在来自其他来源的请求中包含凭据。



希望本文对您有所帮助。感谢您的关注。



All Articles