解决 API 开发中遇到的 CORS 问题

h1>介绍

当你在开发 API的时候,肯定会遇到前端反馈 CORS 的问题,CORS 政策阻止了对 API 的获取访问:对预检请求的响应未通过访问控制检查:请求中不存在“Access-Control-Allow-Origin”标头资源。如果不透明响应满足您的需求,请将请求的模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。

如果你曾经构建过想要与 REST API 交互的 Web 应用程序,你可能熟悉这个错误。如果你还构建了 API,您可能会想:为什么在你在测试 API 时它可以与 Postman 一起使用,而不能在浏览器中使用?你会认为前端程序可能有问题。然而,情况可能并非如此。

image-20210825112214229

下面我讲为你介绍什么是 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 更详细的介绍,请查看文档 https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

如何解决 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 一样适用:你可以将解决方案定制为不那么开放,并且只允许某些来源、方法或标头。

在 flask 的生态中,有一个扩展包 flask-cors,推荐使用这个,非常方便的解决我们所有 CORS 问题,不足的是会对所有源请求开放。

from flask import Flask
from flask_cors import CORS

app = Flask(name) CORS(app)

前端开发人员

前端开发人员可能处于“最糟糕”的境地。然而,这不是你的错,这是很常见的情况。你可能只想与第三方 API 交互,而它只是不断抱怨 CORS。我们能做些什么呢?

理想的解决方案是将这个问题告知 API 所有者,因为从技术上讲,这是他们的错。但是,你可能不会立即得到响应。由于他们发现使用它没有问题,这是你自己的配置错误。如果这是你的情况,请参考这篇文章。但是,与此同时,你可以尝试以下解决方案。

你可以构建一个代理 API,作为与第三方 API 的桥梁。这听起来有点老套,但如果您希望你的网络应用程序正常工作,它可能是你可用的唯一可行解决方案。代理 API 将接收来自你的 Web 应用程序的请求并将它们发送到第三方 API。当第三方 API 响应时,它只会将响应转发到你的 Web 应用程序。由于对第三方 API 的请求不通过浏览器,因此绕过了 CORS 保护。然后,你可以像前两个场景一样配置你自己的代理 API。

最后一个解决方案是使用浏览器插件将所需的标头注入响应。不推荐这样做,因为它只是“自欺欺人”。浏览器插件无法在其他计算机(例如你用户的)上运行,除非他们也有这些插件。但是,如果你在本地进行测试并希望尽快看到一些结果,它仍然很有用。每个浏览器通常都有很多这样的插件。其中之一是 Chrome 的 Allow-Control-Allow-Origin 扩展。

还有关于如何关闭浏览器上的 CORS 检查的教程,但我们不会在这里不介绍,因为它也不能扩展。

结论

这篇文章提供了对 CORS 政策的非常高层次的看法。还有很多东西需要学习,可以在顶部的更多关于 CORS 部分中找到。我针对不同的场景量身定制了解决方案,以帮助你找到适合您需求的解决方案。我希望这篇文章对您有所帮助,因为我个人曾遇到过这些场景,并希望能有一篇这样的文章。

如果你觉得我写的还不错,就关注我吧

解决 API 开发中遇到的 CORS 问题
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue.js 本身并不直接处理CORS跨域问题,因为这通常是服务器端的配置问题,与前端框架无关。但是,当在Vue应用进行API请求时,特别是使用axios等库进行HTTP通信时,可能会遇到跨域限制。Vue2可以通过以下几种方式来间接解决这个问题: 1. **JSONP(不推荐)**:在后端支持下,通过动态创建`<script>`标签并设置`src`属性为服务器提供的JSONP接口,这种方式适用于GET请求且目标域名与当前域名同源的情况。 2. **代理(推荐)**:在开发阶段,可以利用`vue-cli`的`proxyTable`配置,将所有针对非同源API的请求代理到同一域名或特定路径的服务器上。这需要在开发服务器启动时开启。 ```json // vue.config.js module.exports = { devServer: { proxy: { '/api': { target: 'https://your-backend-server.com', // 要代理的目标URL changeOrigin: true, ws: true, // 如果是WebSocket请求 pathRewrite: { '^/api': '' } // 重写请求路径 } } } } ``` 3. **CORS服务器间件**:在生产环境,后端应用需要设置CORS头来允许跨域请求。比如在Node.js的Express,可以添加以下间件: ```javascript app.all('*', function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With'); // 其他CORS相关的头部设置 next(); }); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值