✋🏼🔥 CS 可视化:CORS
每个开发者偶尔都会Access to fetched has been blocked by CORS policy
在控制台里看到那个红色的大错误,这真是令人沮丧!😬 虽然有一些方法可以快速消除这个错误,但今天我们不要想当然!相反,让我们看看 CORS 到底在做什么,以及为什么它实际上是我们的朋友 👏🏼
❗️ 这篇博文我不会讲解 HTTP 的基础知识。如果你想了解更多关于 HTTP 请求和响应的知识,我之前写过一篇小博文🙂 在我的例子中,我使用的是 HTTP/1.1 而不是 HTTP/2,这不会影响 CORS。
在前端,我们经常需要显示位于其他地方的数据!在显示这些数据之前,浏览器首先必须向服务器发出请求以获取这些数据!客户端会发送一个 HTTP 请求,其中包含服务器将数据发送回客户端所需的所有信息 🙂
假设我们正尝试www.mywebsite.com
从位于的服务器获取我们网站上的一些用户信息api.website.com
!
完美!😃 我们刚刚向服务器发送了一个 HTTP 请求,服务器就返回了我们请求的 JSON 数据。
让我们尝试从另一个域名发出完全相同的请求。我们现在不再从 发出请求,而是从位于 的网站发出请求。www.mywebsite.com
www.anotherdomain.com
等等,什么?我们发送了完全相同的请求,但这次浏览器却显示了一个奇怪的错误?
我们刚刚见识了 CORS 的运作方式!💪🏼 让我们看看为什么会发生这个错误,以及它到底意味着什么。
✋🏼 同源策略
Web 强制执行所谓的同源策略。默认情况下,我们只能访问与请求源位于同一源https://mywebsite.com/image1.png
的资源!💪🏼例如,加载位于 的图片是完全没问题的。
当资源位于不同的(子)域、协议或端口时,它就是跨域的!
很酷,但是为什么同源策略会存在呢?
假设同源策略不存在,你不小心点击了你阿姨在 Facebook 上发给你的众多病毒链接之一。这个链接会将你重定向到一个“邪恶网站”,该网站嵌入了一个 iframe,会加载你银行的网站,并通过一些设置的 cookie 成功让你登录!😬
这个“邪恶网站”的开发者让网站能够访问这个 iframe 并与您银行网站的 DOM 内容进行交互,以便代表您将钱汇到他们的账户!
是啊……这可是巨大的安全隐患!我们可不想让任何人轻易访问所有东西😧
幸运的是,同源策略在这里帮了我们大忙!此策略确保我们只能访问来自同一来源的资源。
在这种情况下,源服务器www.evilwebsite.com
试图访问跨域资源www.bank.com
!同源策略阻止了这种情况的发生,并确保了恶意网站的开发者无法访问我们的银行数据🥳
好的,那么...这与 CORS 有什么关系?
🔥 客户端 CORS
虽然同源策略实际上只适用于脚本,但浏览器将此策略“扩展”为 JavaScript 请求:默认情况下,我们只能访问从同一来源获取的资源!
嗯,但是……我们经常需要访问跨域资源🤔也许我们的前端需要与后端 API 交互才能加载数据?为了安全地允许跨域请求,浏览器使用了一种名为CORS的机制!🥳
CORS 代表跨域资源共享。虽然浏览器不允许我们访问非同源的资源,但我们可以使用 CORS 稍微改变一下这些安全限制,同时仍然确保我们能够安全地访问这些资源 🎉
用户代理(例如浏览器)可以使用 CORS 机制来允许跨域请求,否则这些请求会根据 HTTP 响应中某些 CORS 特定标头的值被阻止!✅
当发出跨域请求时,客户端会自动在我们的 HTTP 请求中添加一个额外的标头:Origin
。标头的值Origin
就是请求来自的来源!
为了让浏览器允许访问跨域资源,它需要从服务器的响应中获得某些标头,这些标头指定该服务器是否允许跨域请求!
💻 服务器端 CORS
作为服务器开发人员,我们可以通过在 HTTP 响应中添加额外的标头来确保允许跨源请求,这些标头均以Access-Control-*
🔥开头。根据这些 CORS 响应标头的值,浏览器现在可以允许某些通常会被同源策略阻止的跨源响应!
尽管我们可以使用多个 CORS 标头,但浏览器需要一个标头才能允许跨域资源访问:Access-Control-Allow-Origin
!🙂
此标头的值指定哪些来源被允许访问它们从服务器请求的资源。
如果我们正在开发一个https://mywebsite.com
应该有权访问的服务器,我们可以将该域的值添加到Access-Control-Allow-Origin
标头中!
太棒了!🎉 现在,此标头已添加到服务器返回给客户端的响应中。添加此标头后,如果我们从 发送请求,同策略源将不再限制我们接收位于该源的资源!https://api.mywebsite.com
https://mywebsite.com
浏览器中的 CORS 机制会检查标头的值是否等于请求发送Access-Control-Allow-Origin
的值🤚🏼Origin
在这种情况下,我们的请求的来源是https://www.mywebsite.com
,它在响应头中列出Access-Control-Allow-Origin
!
完美!🎉 我们成功接收了跨域资源!那么,当我们尝试从Access-Control-Allow-Origin
header 中未列出的来源访问这些资源时会发生什么呢?🤔
啊,没错,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 仅允许使用列出的方法发送的跨域请求。
在这种情况下,只有带有 、 或 方法的请求GET
才会POST
被PUT
允许!其他方法(例如PATCH
或 )DELETE
将被阻止❌
如果您对其他可能的 CORS 标头以及它们的用途感到好奇,请查看此列表。
说到PUT
、PATCH
和DELETE
请求,CORS 实际上处理这些请求的方式不同!🙃 这些“非简单”请求会发起所谓的预检请求!
🚀 预检请求
CORS 有两种类型的请求:简单请求和预检请求。一个请求是简单请求还是预检请求取决于请求中的一些值(不用担心,你不必记住这些值,哈哈)。
如果请求是GET
或POST
方法,且没有任何自定义标头,则该请求很简单!任何其他请求,例如带有 、 或 方法的请求PUT
,PATCH
都DELETE
将被预检。
如果你只是好奇一个请求必须满足哪些要求才能成为一个简单的请求,MDN 有一个有用的列表!
好的,但是“预检请求”到底是什么意思,为什么会发生这种情况?
在实际发送请求之前,客户端会生成一个预检请求!预检请求的标头中包含了我们即将发送的实际请求的相关信息Access-Control-Request-*
🔥
这为服务器提供了有关浏览器试图发出的实际请求的信息:请求的方法是什么、附加标头是什么,等等。
服务器收到这个预检请求后,会返回一个空的 HTTP 响应,其中包含服务器的 CORS 标头!浏览器收到这个预检响应(除了 CORS 标头外不包含任何数据),并检查该 HTTP 请求是否应该被允许!✅
如果是这种情况,浏览器就会向服务器发送实际请求,然后服务器会使用我们要求的数据进行响应!
然而,如果不是这种情况,CORS 会阻止预检请求,实际请求永远不会被发送 ✋🏼 预检请求是阻止我们访问或修改尚未启用任何 CORS 策略的服务器上资源的好方法!服务器现在可以免受潜在有害跨域请求的侵害 😃
💡 为了减少与服务器的往返次数,我们可以通过
Access-Control-Max-Age
在 CORS 请求中添加标头来缓存预检响应!这样,浏览器就可以直接使用预检响应,而不必发送新的预检请求!
🍪证书
默认情况下,Cookie、授权标头和 TLS 证书仅在同源请求中设置!但是,我们可能希望在跨源请求中使用这些凭据。也许我们想在请求中包含服务器可以用来识别用户的 Cookie!
虽然 CORS 默认不包含凭据,但我们可以通过添加Access-Control-Allow-Credentials
CORS 标头来更改此设置!🎉
如果我们想要将 cookies 和其他授权标头包含到我们的跨域请求中,我们需要在请求中设置该withCredentials
字段并将标头添加到响应中。true
Access-Control-Allow-Credentials
一切就绪!我们现在可以在跨域请求中包含凭据了🥳
虽然我想我们都同意 CORS 错误有时会令人沮丧,但令人惊奇的是,它使我们能够在浏览器中安全地进行跨域请求(它应该得到更多的喜爱哈哈)✨
显然,同源策略和 CORS 的内容远比我这篇博文所能涵盖的要多得多!好在,如果你想了解更多,有很多很棒的资源,比如这个或W3 规范💪🏼
和往常一样,欢迎随时联系我!😊
文章来源:https://dev.to/lydiahallie/cs-visualized-cors-5b8h