可视化解析CORS

·  阅读 659
 可视化解析CORS

当我们在控制条太看到Access to fetched has been blocked by CORS policy这个红色错误的时候,每一个都会感到沮丧!虽然有一些方法可以快速摆脱这个错误,但今天让我们看看 CORS 实际上在做什么,以及为什么它实际上是我们的朋友

❗️ 在这篇博文中,我不会解释 HTTP 基础知识。如果你想了解更多关于 HTTP 请求和响应的信息,我不久前写了一篇关于它的小博文🙂 在我的例子中,我使用 HTTP/1.1 而不是 HTTP/2,这不会影响 CORS。

在前端,我们经常需要显示位于其他地方的数据!在我们可以显示这些数据之前,浏览器首先必须向服务器发出请求以获取该数据!客户端发送一个 HTTP 请求,其中包含服务器需要的所有信息,以便将该数据发送回客户端 🙂

假设我们试图 从www.mywebsite.comapi.website.com发生请求

LnB05O.gif

😃 我们刚刚向服务器发送了一个 HTTP 请求,然后服务器响应了我们请求的 JSON 数据。

现在让我们尝试向另一个域发送完全相同的请求。现在我们通过www.anotherdomain.comapi.website.com发送完全相同的请求

LnBMSR.gif

等等,什么?我们发送了完全相同的请求,但这次浏览器向我们显示了一个奇怪的错误?

我们刚刚看到了 CORS 的作用!💪🏼 现在让我们看看为什么会出现这个错误,以及它究竟意味着什么。

✋🏼 同源政策

浏览器中存在称为同源策略的东西。默认情况下,我们只能访问请求位于同一源的资源!例如请求https://mywebsite.com/image1.png这个资源就是完成可行的

但是当资源位于不同的(子)域、协议或端口时,它就是跨源的!

LnfGPu.png

但为什么同源策略甚至存在?

假设同源策略不存在,并且您不小心点击了您的阿姨在 Facebook 上发送给您的众多病毒链接之一。此链接会将您重定向到一个“邪恶网站”,该网站嵌入了 iframe,可加载您银行的网站,并通过一些设置的 cookie 成功登录!😬

这个“邪恶网站”的开发者使该网站可以访问这个 iframe 并与您银行网站的 DOM 内容进行交互,以便代表您向他们的账户汇款!

LnfL44.gif

是的……这是一个巨大的安全风险!我们不希望任何人都能访问所有内容 😧

幸运的是,同源策略在这里帮助了我们!此策略确保我们只能访问来自同一来源的资源。

LnfPMX.gif

在这种情况下,源www.evilwebsite.com尝试从www.bank.com! 同源策略阻止了这种情况的发生,并确保邪恶网站的开发人员不能只是访问我们的银行数据🥳

好的,所以......这与 CORS 有什么关系?

🔥 客户端 CORS

虽然同源策略实际上只适用于脚本,但浏览器为 JavaScript 请求“扩展”了这个策略:默认情况下,我们只能访问来自同源的资源!

Lnfn96.gif

但是...我们经常要访问跨域资源🤔 我们的前端需要与我们的后端 API 交互才能加载数据?为了安全地允许跨域请求,浏览器使用了一种叫做CORS的机制!🥳

CORS 代表跨域资源共享。尽管浏览器不允许我们访问位于不同来源的资源,但我们可以使用 CORS 稍微更改这些安全限制,同时仍然确保我们安全地访问这些资源 🎉

用户代理(例如浏览器)可以使用 CORS 机制,根据 HTTP 响应中某些特定于 CORS 的标头的值,允许跨域请求,否则这些请求将被阻止!✅

当一个跨域请求,客户端会自动添加一个额外的头给我们的HTTP请求:OriginOriginheader的值就是请求的来源!

Lnf77T.gif

为了让浏览器允许访问跨域资源,它需要来自服务器响应的某些标头,这些标头指定此服务器是否允许跨域请求!

💻 服务端CORS

作为服务器开发人员,我们可以通过在 HTTP 响应中添加额外的响应头来确保允许跨域请求,这些标头都以Access-Control-*开头,基于这些 CORS 响应标头的值。浏览器现在可以允许我们访问那些通常会被同源策略阻止的跨域请求

尽管我们可以使用多个 CORS 标头,但浏览器需要一个标头以允许跨源资源访问: Access-Control-Allow-Origin! 🙂 此标头的值指定允许哪些源访问它们从服务器请求的资源

如果我们正在开发一个https://mywebsite.com应该可以访问的服务器,我们可以将该域的值添加到Access-Control-Allow-Origin标头中!

Lnfd3Q.gif

此标头现在已添加到服务器发送回客户端的响应中。通过添加此头同源策略将不再阻止我们接收来自https://api.mywebsite.com的响应。

LnflPh.gif浏览器中的 CORS 机制会检查Access-Control-Allow-Originheader 的值是否等于Origin请求发送的值🤚🏼

在这种情况下,我们请求的源是https://www.mywebsite.com,它列在Access-Control-Allow-Origin响应头中!

LnfcmL.gif

完美的!🎉 我们能够成功接收到跨域资源!那么,当我们试图从未在Access-Control-Allow-Origin标头中列出的来源访问这些资源时会发生什么?🤔

LnfNui.gif

啊,是的,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 标头之一。服务器开发人员可以扩展服务器的 CORS 策略以(禁止)允许某些请求!💪🏼

另一个常见的标题是Access-Control-Allow-Methods标题!CORS 仅允许使用列出的方法发送的跨域请求。

LnfmQC.gif

在这种情况下,只允许带有GET, POST, 或PUT方法的请求!其他方法如PATCHDELETE将被阻止❌

说到PUTPATCHDELETE请求,CORS实际处理这些请求不同!🙃 这些“非简单”的请求发起了一个叫做预检请求的事情!

🚀 预检请求

CORS 有两种类型的请求:简单请求预检请求。请求是简单的还是预检取决于请求中的一些值(别担心,你不必记住这个,哈哈)。

当请求是一个GETorPOST方法并且没有任何自定义标头时,请求很简单!任何其它请求,诸如与请求PUTPATCHDELETE方法,将被预检。

好的,但是“预检请求”甚至是什么意思,为什么会发生这种情况?

在发送实际请求之前,客户端会生成一个预检请求!预检请求在其Access-Control-Request-*标头中包含有关我们即将执行的实际请求的信息🔥

这为服务器提供了有关浏览器尝试发出的实际请求的信息:请求的方法是什么,附加的标头是什么,等等。

LnfvCR.gif

服务器收到这个预检请求,并发送一个带有服务器 CORS 标头的空 HTTP 响应!浏览器收到预检响应,除了 CORS 标头之外不包含任何数据,并检查是否应该允许 HTTP 请求!✅

LnfBfG.gif

如果是这种情况,浏览器会将实际请求发送到服务器,然后服务器以我们要求的数据进行响应!

LnfKYT.gif

但是,如果不是这样,CORS 将阻止预检请求,而实际请求永远不会发送✋🏼

预检请求是阻止我们访问或修改未启用任何 CORS 策略的服务器上的资源的好方法

服务器现在受到保护,免受可能不需要的跨域请求 😃

💡 为了减少到我们服务器的往返次数,我们可以通过向Access-Control-Max-AgeCORS 请求添加标头来缓存预检响应!我们可以通过这种方式缓存预检响应,浏览器可以使用它而不是发送新的预检请求!

🍪 证书

默认情况下,Cookie、授权标头和 TLS 证书仅在同源请求上设置!但是,我们可能希望在跨域请求中使用这些凭据。也许我们想在请求中包含 cookie,服务器可以使用这些 cookie 来识别用户!

尽管默认情况下 CORS 不包含凭据,但我们可以通过添加Access-Control-Allow-CredentialsCORS 标头来更改它!🎉

如果我们想在我们的跨域请求中包含 cookie 和其他授权标头,我们需要在请求上将该withCredentials字段设置为true并将Access-Control-Allow-Credentials标头添加到响应中。

LnfhCE.gif

搞定!我们现在可以在跨域请求中包含凭据 🥳

虽然我认为我们都同意 CORS 错误有时会令人沮丧,但令人惊讶的是,它使我们能够在浏览器中安全地发出跨域请求

显然,同源策略和 CORS 的内容比我在这篇博文中所能涵盖的要多得多!幸运的是,如果你想阅读更多关于它的信息,有很多很棒的资源,比如这个W3 规范💪🏼

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改