使用 Axios 访问控制源头错误

IT技术 javascript reactjs axios
2021-03-15 22:46:45

我正在 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 
6个回答

我会尝试一下这个复杂的主题。

什么是原产地

源本身是主机的名称(方案、主机名和端口)ighttps://www.google.com或者可以是本地打开的文件file://等。它是某些东西(ig 网页)的来源。当您打开 Web 浏览器并转到 时https://www.google.com,显示给您的网页的来源是https://www.google.com您可以在 Chrome Dev Tools 中看到Security

在此处输入图片说明

如果您通过文件资源管理器(不通过服务器提供)打开本地 HTML 文件,则同样适用:

在此处输入图片说明

这与CORS问题有什么关系?

当您打开浏览器并转到https://website.com该网站时,该网站的来源将是https://website.com. 该网站很可能只会获取图像、图标、js 文件并对 进行 API 调用https://website.com,基本上它调用的是与提供服务的服务器相同的服务器。它正在调用同源

例如,如果您打开 Web 浏览器并打开本地 HTML 文件,并且在该 html 文件中存在想要向 google 发出请求的 javascript,则会出现以下错误:

在此处输入图片说明

同源策略告诉浏览器阻止跨源请求。在这种情况下, originnull正在尝试向https://www.google.com跨源请求发出请求由于设置了 CORS 策略,并且该策略是不允许跨域请求,因此浏览器将不允许这样做。

如果我的页面是从本地主机上的服务器提供的,则同样适用:

在此处输入图片说明

本地主机服务器示例

如果我们使用以下代码在 localhost:3000 上托管我们自己的 localhost 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 服务器发出请求)目录,将发生以下错误:

在此处输入图片说明

由于网页不是从 localhost:3000 上的 localhost 服务器提供的,并且通过文件资源管理器,源与服务器 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 策略,并且会得到你想要的。

示例流程

以下摘自:https : //web.dev/cross-origin-resource-sharing/#how-does-cors-work

请记住,同源策略告诉浏览器阻止跨源请求。当你想从不同的源获取公共资源时,资源提供服务器需要告诉浏览器“请求来自的这个源可以访问我的资源”。浏览器记住这一点并允许跨源资源共享。

  • 步骤一:客户端(浏览器)请求当浏览器进行跨域请求时,浏览器会添加一个带有当前源(方案、主机和端口)的 Origin 标头。

  • 第 2 步:服务器响应 在服务器端,当服务器看到这个标头,并希望允许访问时,它需要在响应中添加一个 Access-Control-Allow-Origin 标头,指定请求的来源(或 * 允许任何来源.)

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

更多链接

这是另一个很好的答案,更详细地说明了正在发生的事情:https : //stackoverflow.com/a/10636765/1137669

这是一个非常全面的答案。应该作为一个很好的参考。
2021-05-18 22:46:45

如果您的后端支持 CORS,您可能需要在请求中添加以下标头:

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

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

但在大多数情况下,更好的解决方案是配置反向代理,以便您的服务器能够将请求从前端重定向到后端,而无需启用 CORS。

您可以在此处找到有关 CORS 机制的文档:https : //developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

"Access-Control-Allow-Origin" 是响应标头,因此将其添加到请求中实际上没有任何用处。
2021-04-24 22:46:45
你有没有像这个例子中那样完成 CORS 的设置?restdb.io/docs/apikeys-and-cors
2021-05-18 22:46:45
我已经添加了它,'Access-Control-Allow-Origin':'*','Access-Control-Allow-Methods':'GET,PUT,POST,DELETE,PATCH,OPTIONS',但是我现在得到错误“在预检响应中,Access-Control-Allow-Headers 不允许请求标头字段 Access-Control-Allow-Origin” 我使用 restdb.io 作为我的 api 端点。
2021-05-20 22:46:45

我有一个类似的问题,我发现在我的情况下withCredentials: true,请求正在激活 CORS 检查,同时在标头中发出相同的内容将避免检查:

原因:在 CORS 标头“Access-Control-Allow-Credentials”中预期为“true”

不使用

withCredentials: true

但设置

'Access-Control-Allow-Credentials':true

在标题中。

不要使用 withCredentials: true 解决了我的问题.. 但我没有在 req 标头中设置 'Access-Control-Allow-Credentials':true .. 相反,我在服务器端的 web.config 中添加了它并解决了问题。
2021-05-10 22:46:45

我有同样的错误。我通过使用npm i cors. 然后,您需要将其添加到您的代码中:

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

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

这对我有用,还请注意,您必须app.use(cors())在请求之前使用
2021-05-12 22:46:45

在这种情况下,对请求使用 Access-Control-Allow-Origin 标头将无济于事,而此标头只能用于响应...

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

添加crossorigin:true到标题对我有用。干杯
2021-05-13 22:46:45