解决 API 开发中遇到的 CORS 问题
Posted wzlinux
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决 API 开发中遇到的 CORS 问题相关的知识,希望对你有一定的参考价值。
介绍
当你在开发 API的时候,肯定会遇到前端反馈 CORS 的问题,CORS 政策阻止了对 API 的获取访问:对预检请求的响应未通过访问控制检查:请求中不存在“Access-Control-Allow-Origin”标头资源。如果不透明响应满足您的需求,请将请求的模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。
如果你曾经构建过想要与 REST API 交互的 Web 应用程序,你可能熟悉这个错误。如果你还构建了 API,您可能会想:为什么在你在测试 API 时它可以与 Postman 一起使用,而不能在浏览器中使用?你会认为前端程序可能有问题。然而,情况可能并非如此。
下面我讲为你介绍什么是 CORS,以及如何修复这个问题:
CORS
What is CORS
CORS(Cross-Origin Resource Sharing) 代表跨域资源共享。这是一种限制来自不同来源(domain)的请求的机制。来自不同来源的请求称为跨域请求。当您的站点需要从其他服务加载数据时,跨域请求至关重要。
CORS 允许服务器指定谁可以访问他们的资源以及如何访问。浏览器通过向服务器发送测试请求(preflight)并检查它是否被允许来遵循服务器的策略。
Why CORS
其背后的基本原理是允许一个源上的服务器 (API) 限制其他源的行为。例如,允许一个源读取和写入数据,而其他源仅读取数据。因此,默认情况下通常允许像 GET 这样的请求。但是,PUT、DELETE 和有时 POST 会受到限制。
How does CORS work
当浏览器即将发送将触发 CORS 到不同来源的请求时,例如 PUT 请求,它不会立即发送实际请求。相反,它将发送所谓的 preflight request,用于测试服务器是否允许通信。如果服务器以成功状态响应,则浏览器将发送实际请求。否则,它将拒绝请求,返回 405 状态代码。
如何解决 CORS 问题
CORS 问题可能非常烦人,尤其是对于学习者。本文将总结可以节省您在 StackOverflow 上搜索时间的解决方案。解决方案取决于您的特定场景:更具体地说,取决于您对服务器的控制程度。我们将从最好的情况走向最坏的情况:
完全控制服务器
如果你是将 API 部署到您自己的服务器上的人,那么你处于最佳情况。您需要做的就是配置你的服务器,假设你使用的是 nginx。如果不是,你仍然可以查看以下方案,这些方案也可能解决此问题。
下面是 nginx 的配置文件,参考来自:https://enable-cors.org/server_nginx.html
if ($request_method = \'OPTIONS\') {
add_header \'Access-Control-Allow-Origin\' \'*\';
add_header \'Access-Control-Allow-Methods\' \'GET, POST, OPTIONS\';
# Custom headers and headers various browsers *should* be OK with but aren\'t
add_header \'Access-Control-Allow-Headers\' \'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range\';
# Tell client that this pre-flight info is valid for 20 days
add_header \'Access-Control-Max-Age\' 1728000;
add_header \'Content-Type\' \'text/plain; charset=utf-8\';
add_header \'Content-Length\' 0;
return 204;
}
if ($request_method = \'POST\') {
add_header \'Access-Control-Allow-Origin\' \'*\';
add_header \'Access-Control-Allow-Methods\' \'GET, POST, OPTIONS\';
add_header \'Access-Control-Allow-Headers\' \'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range\';
add_header \'Access-Control-Expose-Headers\' \'Content-Length,Content-Range\';
}
你可以根据自己的需要进行定制。例如,你可以只允许你的 Web 应用程序域,而不是对所有来源使用通配符。你还可以选择仅允许特定方法和标题通过。
此解决方案允许你在不篡改 API 代码的情况下配置 CORS,这在大多数情况下是理想的。如果这不是你想要的,或者你无法控制服务器,你可能会在下一个场景中找到你的解决方案。
API 开发人员
在这种情况下,你完全部署了 API,但是你并没有服务器的控制权,因此你无法控制服务器配置。本节将指导你在后端代码中添加必要的标头。
没有通用的服务器端语言或框架,但我们至少可以使用一个非常流行的选项来展示一个解决方案。
这里我将使用 Flask 应用程序进行演示,这是一个非常流行的 Python 框架,我也正是用这个框架来开发简单的 API 接口的。
app = Flask(__name__)
@app.after_request
def after_request(response):
response.headers.add(\'Access-Control-Allow-Origin\', \'*\')
response.headers.add(\'Access-Control-Allow-Headers\', \'Content-Type\')
return response
上面的代码块显示了如何在处理请求之后和发送响应之前添加额外的标头。这与 Nginx 一样适用:你可以将解决方案定制为不那么开放,并且只允许某些来源、方法或标头。
前端开发人员
前端开发人员可能处于“最糟糕”的境地。然而,这不是你的错,这是很常见的情况。你可能只想与第三方 API 交互,而它只是不断抱怨 CORS。我们能做些什么呢?
理想的解决方案是将这个问题告知 API 所有者,因为从技术上讲,这是他们的错。但是,你可能不会立即得到响应。由于他们发现使用它没有问题,这是你自己的配置错误。如果这是你的情况,请参考这篇文章。但是,与此同时,你可以尝试以下解决方案。
你可以构建一个代理 API,作为与第三方 API 的桥梁。这听起来有点老套,但如果您希望你的网络应用程序正常工作,它可能是你可用的唯一可行解决方案。代理 API 将接收来自你的 Web 应用程序的请求并将它们发送到第三方 API。当第三方 API 响应时,它只会将响应转发到你的 Web 应用程序。由于对第三方 API 的请求不通过浏览器,因此绕过了 CORS 保护。然后,你可以像前两个场景一样配置你自己的代理 API。
最后一个解决方案是使用浏览器插件将所需的标头注入响应。不推荐这样做,因为它只是“自欺欺人”。浏览器插件无法在其他计算机(例如你用户的)上运行,除非他们也有这些插件。但是,如果你在本地进行测试并希望尽快看到一些结果,它仍然很有用。每个浏览器通常都有很多这样的插件。其中之一是 Chrome 的 Allow-Control-Allow-Origin 扩展。
还有关于如何关闭浏览器上的 CORS 检查的教程,但我们不会在这里不介绍,因为它也不能扩展。
结论
这篇文章提供了对 CORS 政策的非常高层次的看法。还有很多东西需要学习,可以在顶部的更多关于 CORS 部分中找到。我针对不同的场景量身定制了解决方案,以帮助你找到适合您需求的解决方案。我希望这篇文章对您有所帮助,因为我个人曾遇到过这些场景,并希望能有一篇这样的文章。
如果你觉得我写的还不错,就关注我吧
以上是关于解决 API 开发中遇到的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章
如何绕过 CORS 并从 CORS 阻止的 API 获取数据?
基于.Net Framework 4.0 Web API开发:ASP.NET Web APIs AJAX 跨域请求解决办法(CORS实现)