使用 Axios 的访问控制起源头错误

我在一个 React Web 应用程序中使用 Axios 进行 API 调用,然而,我在 Chrome 中得到了这个错误:

XMLHttpRequest cannot load
https://example.restdb.io/rest/mock-data. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8080' is therefore not allowed
access.
{
axios
.get("https://example.restdb.io/rest/mock-data", {
headers: {
"x-apikey": "API_KEY",
},
responseType: "json",
})
.then((response) => {
this.setState({ tableData: response.data });
});
}

我也阅读了关于 Stack Overflow 的几个答案,都是关于同一个问题的,题目是 Access-Control-Allow-Origin,但仍然不知道如何解决这个问题。我不想在 Chrome 中使用扩展或者使用临时黑客技术来解决这个问题。请提出解决上述问题的标准方法。

在尝试了几个我试过的答案之后,

headers: {
'x-apikey': '59a7ad19f5a9fa0808f11931',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
},

现在我得到的错误是,

Request header field Access-Control-Allow-Origin is not
allowed by Access-Control-Allow-Headers in preflight response
486491 次浏览

If your backend support CORS, you probably need to add to your request this header:

headers: {"Access-Control-Allow-Origin": "*"}

[更新] Access-Control-Allow-Origin是一个响应头-因此,为了启用 CORS-您需要将这个头添加到来自您的服务器的响应中。

But for the most cases better solution would be configuring the 反向代理服务器, so that your server would be able to redirect requests from the frontend to backend, without enabling CORS.

You can find documentation about CORS mechanism here: Https://developer.mozilla.org/en-us/docs/web/http/access_control_cors

在这种情况下,对请求使用访问控制-允许-起源标头不会帮助您,而这个标头只能用于响应..。

为了使其正常工作,您可能应该将此标题添加到您的响应中。您还可以尝试将头 crossorigin:true添加到请求中。

据我所知,问题是请求从 localhost: 3000发送到 localhost: 8080,而浏览器拒绝 CORS 这样的请求。所以解决方案就是创建代理

我的解决办法是:

import proxy from 'http-proxy-middleware'
app.use('/api/**', proxy({ target: "http://localhost:8080" }));

在节点 js (后端)中,使用 cors npm 模块

$ npm install cors

然后添加这些行以支持访问控制-允许-起源,

const express = require('express')
const app = express()
app.use(cors())
app.get('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'});
});

You can achieve the same, without requiring any external module

app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});

我也遇到过类似的问题,我发现在我的情况下,请求中的 withCredentials: true激活了 CORS 检查,而在标题中发出相同的检查会避免检查:

原因: CORS 报头“ Access-Control-allow-Credential”中的预期“ true”

不要使用

withCredentials: true

但已经定下来了

'Access-Control-Allow-Credentials':true

in the headers.

 },
"proxy": "http://localhost:8080",
"devDependencies": {

在 package.json 中使用代理

$ npm install cors

在从 npm 安装 cors 之后,将下面的代码添加到您的节点应用程序文件中。它解决了我的问题。

var express = require('express')
var cors = require('cors')
var app = express()


app.use(cors())

首先,CORS 肯定是服务器端的问题,而不是客户端的问题,但我非常肯定服务器代码在我的情况下是正确的,因为其他应用程序在不同的域上使用同一个服务器。这个问题的解决方案在其他答案中有更详细的描述。

当我开始对自定义实例使用 axios时,问题就出现了。在我的例子中,当我们在 axios实例中使用 baseURL,然后尝试从任何地方进行 GETPOST调用时,axios 在 baseURL 和请求 URL 之间添加了一个斜杠/,这是一个非常具体的问题。这也说得通,但这是个隐藏的问题。我的 Laravel 服务器正在重定向以删除导致这个问题的尾部斜杠。

一般来说,飞行前 OPTIONS请求不喜欢重定向。如果您的服务器使用301状态代码重定向,则它可能被缓存在不同的级别。所以,一定要检查并避免它。

I had the same error. I solved it by installing CORS in my backend using npm i cors. You'll then need to add this to your code:

const cors = require('cors');
app.use(cors());

这为我修复了它; 现在我可以使用 AJAX 发布我的表单,而不需要添加任何自定义的标题。

我在尝试创建 React Axios 实例时遇到了类似的问题。

我使用下面的方法解决了这个问题。

const instance = axios.create({
baseURL: "https://jsonplaceholder.typicode.com/",
withCredentials: false,
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',
}
});

试试代理服务器 Json 添加代码:

"proxy":"https://localhost:port"

and restart npm enjoy

一样的密码

const instance = axios.create({
baseURL: "/api/list",
 

});
npm i cors
const app = require('express')()
app.use(cors())

以上代码对我很有用。

我来试试这个复杂的题目。

什么是 起源

原点本身是一个主机(模式、主机名和端口)的名称,例如 https://www.google.com,或者可以是一个本地打开的文件 file://等等。它是某些东西(比如网页)的起源地。当你打开你的网页浏览器,转到 https://www.google.com,显示给你的网页的原点是 https://www.google.com。你可以在 Security下的 Chrome 开发工具中看到这一点:

如果你通过你的文件浏览器打开一个本地 HTML 文件(不是通过服务器提供的) :

这和 CORS问题有什么关系?

当你打开浏览器,进入 https://website.example,那个网站将会有 https://website.example的起源。这个网站将 很可能只有获取图像,图标,js 文件和做对 https://website.example的 API 调用,基本上是调用相同的服务器,因为它是从。它正在对同一个源进行调用.

如果你打开你的浏览器,打开一个本地 HTML 文件,在这个 HTML 文件中有一个 JavaScript,它想要对 Google 做一个请求,例如,你会得到以下错误:

同源策略告诉浏览器阻止跨源请求。在这个实例中,起源 null尝试对 https://www.google.com(cross-origin request)执行请求。浏览器将不允许这样做,因为 CORS 策略已经设置,并且该策略是不允许跨来源请求的。

如果我的页面来自本地主机上的服务器,也是如此:

本地主机服务器示例

如果我们使用以下代码在 localhost:3000上运行我们自己的本地主机 API 服务器:

const express = require('express')
const app = express()


app.use(express.static('public'))


app.get('/hello', function (req, res) {
// res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})


app.listen(3000, () => {
console.log('alive');
})

然后从文件浏览器打开一个 HTML 文件(向 localhost:3000服务器发出请求)目录,会发生以下错误:

由于 Web 页面不是从 localhost:3000上的本地主机服务器提供的,并且通过文件浏览器,其起源不同于服务器 API 起源,因此正在尝试跨起源请求。由于 CORS 策略,浏览器正在停止此尝试。

但如果我们去掉评论的那句话:

const express = require('express')
const app = express()


app.use(express.static('public'))


app.get('/hello', function (req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.send('Hello World');
})


app.listen(3000, () => {
console.log('alive');
})

现在再试一次:

它可以工作,因为发送 HTTP 响应的服务器现在包含一个头信息,声明跨源请求可以发生在服务器上,这意味着浏览器将允许它发生,因此没有错误。

如何修理东西(下列其中之一)

  • 从您发出的请求所在的位置(同一主机)提供该页面。
  • 允许服务器通过在响应头中显式声明来接收跨源请求。
  • 如果使用反向代理(如 Nginx) ,请将 Nginx 配置为发送允许 CORS 的响应头。
  • 别用浏览器。例如,使用 cURL,它不像浏览器那样关心 CORS 策略,并且会得到您想要的东西。

示例流

以下内容摘自: 跨来源资源共享(CORS)

请记住,同源策略告诉浏览器阻止 当您希望从 different origin, the resource-providing server needs to tell the 浏览器”请求的来源可以访问我的 浏览器会记住这一点,并允许跨来源的资源 分享。

  • 步骤1: 客户端(浏览器)请求当浏览器发出跨源请求时,浏览器会添加一个 OriginHeader,其中包含 当前来源(方案、主机和端口)。

  • 步骤2: 服务器响应在服务器端,当服务器看到此标头并希望允许访问时,它需要添加一个 属性的响应的访问-控制-允许-起源标头 请求来源(或 * 允许任何来源)

  • 步骤3: 浏览器接收响应当浏览器通过适当的 Access-Control-allow-Origin 标头看到此响应时, 浏览器允许与客户端站点共享响应数据。

更多链接

Here is another good answer, more detailed as to what is happening: https://stackoverflow.com/a/10636765/1137669

I imagine everyone knows what cors is and what it is for. 以一种简单的方式,例如,如果您使用 nodejs 和 Express 进行管理,那么启用它就是这样的

依赖性:

Https://www.npmjs.com/package/cors

app.use (
cors ({
origin: "*",
... more
})
);

而对于本地浏览器请求的问题,它只是安装这个扩展谷歌铬。

名称: 允许 CORS: 访问-控制-允许-起源

https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=es

This allows you to enable and disable cros in local, and problem solved.

对于 Spring Boot-React js 应用程序,我在控制器上添加了 @CrossOrigin注释,它可以工作:

@CrossOrigin(origins = {"http://localhost:3000"})
@RestController
@RequestMapping("/api")

但是注意添加 localhost 正确 = > “ http://localhost:3000”,而不是在结尾处添加“/”= > “ http://localhost:3000/”,这是我的问题。

After a long time of trying to figure out how CORS works. I tried many way to fix it in my FE and BE code. Some ways CORS errors appearance, some ways the server didn't receive body from client, and other errors...

最终得到了这个,我希望这能帮到某人:

BE code (NodeJS + Express)

var express = require("express");
const cors = require("cors");


var app = express();
app.use(
cors({
origin: "*",
})
);


app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
next();
});


// your routers and codes


My FE code (JS):

fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Connection: 'Keep-Alive',
Authorization: `Bearer test`,
},
body: JSON.stringify(data),
});

您可以使用自定义配置创建一个新的 axios 实例,然后使用这个新配置的实例,
使用 axios-configure.js创建一个文件,添加这个可共享的导出方法并使用这个 preconfigured import,而不是像我们传统上使用的那样直接导入 axios,

import axios from 'axios';
import baseUrl from './data-service';


const app = axios.create({
baseURL: baseUrl,
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
},
withCredentials: true
})


export default app;

使用这个导出函数,比如,

import axios from '../YOUR_DIRECTORY/axios-configure';
axios.get();// wont throw cors

不要
然后使用 axios.get()它将不扔 cors为我们工作,

NOTE this solution will work for them who facing CORS at local environment as local starts at 5000 and backend at 8080, but in production, build gets deployed from java 8080 no CORS in productions (Facing CORS at only local environment)

对于任何人谁使用的 Cors 包改变

 const cors = require('cors');
app.use(cors());

const cors = require('cors');
app.use(cors({credentials: true, origin: 'http://localhost:5003'}));

Http://localhost:5003更改为客户端域

在某些特定情况下可以使用 cors 代理 -https://cors.sh