从前端修复跨源资源共享(CORS)。
大多数前端开发人员都会遇到 CORS 问题,他们会像我一样尝试使用 Stack overflow 上的解决方案来解决它,但有些结果是错误的,有些则没有完整解释以便更好地理解。
在本文中,我将讨论 CORS 以及如何从前端(客户端)修复它。
知己知彼,百战不殆!CORS 是什么?👹👹
常见的跨域资源共享 (CORS) 是一种机制,允许从提供第一个资源的域之外的另一个域请求网页上的受限资源。
它为什么存在?🤔
保护我们!它是我们的朋友!💯🐕
大多数情况下,网站需要将资源托管在与网站相同的位置,例如,对为网站提供服务的同一后端进行 API 调用。🏡
因此,此政策将成为第一层保护,以避免其他陌生人使用我们的 API。⚔️
为什么我们最终会遇到 CORS 问题?
因为在某些情况下,我们需要将资源从一个来源请求到另一个来源。例如,当我们的 API 与我们的网站托管在不同的域中(任何第三方 API),或者当您需要使用 Web 字体时。
CORS 默认不允许这样做,因此会出现错误,可以在浏览器控制台中看到。
我们的浏览器和请求的目的地之间发生了什么?
Web 浏览器可以使用特殊的标头来确定 XMLHttpRequest 调用是否应继续或失败。
让我们了解更多技术细节……👇👇👇👇👇👇👇
OPTIONS 请求 🧐
大多数人都知道基本的请求方法(POST、GET、PUT),但并非所有人都熟悉 OPTIONS 方法。此请求方法用于向特定端点询问其支持的通信选项。
此请求用于确定服务器的 CORS 功能,进而确定目标 CORS 协议是否被理解。如果 OPTIONS 调用的结果表明请求无法执行,则不会执行对服务器的实际请求。
OPTIONS请求中包含的选项如下:
-
Access-Control-Request-Method
:请求的预期方法(例如 GET 或 POST) -
Access-Control-Request-Headers
:指示将随请求一起发送的自定义标头 -
Origin
:包含脚本当前来源的常见来源标头
所以我们的客户问:
“_I would like to make a GET request with the Content-Type and Accept headers from http://localhost:3000 — is that possible?_”.
curl -i -X OPTIONS localhost:3001/api/ping
'Access-Control-Request-Method: GET'
'Access-Control-Request-Headers: Content-Type, Accept'
'Origin: <http://localhost:3000>'
服务器会Access-Control-*
在响应中包含一些标头,以指示是否允许后续请求。这些标头包括:
-
Access-Control-Allow-Origin
:允许发出请求的来源,或者 *(如果可以从任何来源发出请求)。 -
Access-Control-Allow-Methods
:允许的 HTTP 方法的逗号分隔列表。 -
Access-Control-Allow-Headers
:允许发送的自定义标头的逗号分隔列表。 -
Access-Control-Max-Age
:在进行另一次调用之前,可以缓存对 pref light 请求的响应的最长持续时间。
然后浏览器会检查响应以决定是否继续请求者是否放弃它。
所以我们的服务器正在回复🤓:
“我接受来自每个域 (*) 的请求,并允许以下方法 GET、HEAD、PUT、PATCH、POST、DELETE”
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Vary: Access-Control-Request-Headers
Access-Control-Allow-Headers: Content-Type, Accept
Content-Length: 0
Date: Fri, 05 Apr 2019 11:41:08 GMT
Connection: keep-alive
因此,如果客户端尝试执行的第一个请求满足要求,它就会发送初始请求,并且该过程会正常进行,每个人都会很高兴🎊🎊🎉😁。如果没有,您会收到一个戏剧性的 CORS 错误,这意味着您的初始请求甚至没有发送,您会哭😭。
那么,我们该如何解决这个问题呢?🔧
如果在开发过程中出现 CORS 问题,因为我们使用的是本地开发服务器,这不是“错误”,而只是一个不便之处,我们将学习如何解决。
🤔也许您正在考虑更改“origin”标头以避免 CORS,忘掉它吧,“origin”是一个禁止的标头,这意味着您无法更新它。🙄
🤔下一个也是最常见的解决方案是要求服务器将标头设置为***(允许所有)**。
💩🤦♀️这不是一个好的做法,前端的最终域名当然应该列入白名单,但简单地允许所有域名是一种不值得鼓励的安全漏洞。🤦♂️💩
虽然开发时我们的域名通常是 localhost,而对外开放的域名是我们的 IP,除非你将其列入白名单,但如果 IP 发生变化,这可能会无效,除非你允许所有域名,否则 CORS 限制永远不会允许它。🤷♂️🤷♀️
🤓现在,绕过此限制最有效、最省事的开发方法是使用代理。这样,我们向允许我们请求的代理服务器发出请求,然后该代理服务器再向原始 API 域发出请求。此请求将由代理服务器(而不是浏览器)执行,因此它将能够不受限制地执行请求。它还会将原始内容作为 API 的响应发送回我们的前端。👌
已经构建了代理服务器,因此您不必创建自己的代理服务器,只需从 npm 安装一个 cors-proxy 即可。
设置 CORS 代理
就我而言,我使用了它:
https://www.npmjs.com/package/local-cors-proxy,但有数百个。您可以将其安装在项目本地,也可以安装在计算机上的全局,具体取决于您是否要将其添加到项目开发依赖项中并在开发过程中运行。
(通常自动化是一个好主意,只是说一下🙄)
在这种情况下,步骤很容易遵循,但为了以防万一,我将逐一回顾它们:
简单示例
我们要请求的具有 CORS 问题的 API 端点:
https://www.yourdomain.ie/movies/list
- 通过运行以下命令安装依赖项:
npm i local-cors-proxy
- 如果出现问题,请启动特定域的代理:
lcp --proxyUrl https://www.yourdomain.ie
- 在您的客户端中更新您的 API 端点以将其指向您的代理:从此:
<https://www.yourdomain.ie/movies/list>
对此:
<http://localhost:8010/proxy/movies/list>
CORS 已修复🎉🎉🎉🎉
结论
我希望你现在已经明白,CORS🧙♂️ 没有什么神奇之处,它只是“后端应该修复”的问题。但是,如果你正在使用公共 API,我们确实遇到了这个问题,现在你可以自己修复 CORS 了。谢谢
鏂囩珷鏉ユ簮锛�https://dev.to/mopharr/fixing-cross-origin-resource-sharing-cors-from-the-front-end-5hcb