【问题标题】:Access Control Origin Header error using Axios使用 Axios 的访问控制 Origin Header 错误
【发布时间】:2018-02-09 00:53:16
【问题描述】:

我在 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 中使用扩展程序或使用临时 hack 来解决这个问题。请提出解决上述问题的标准方法。

在尝试了几个答案后,我尝试了这个,

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 

【问题讨论】:

  • 检查您收到的响应中的 HTTP 响应代码。您是否从中获得 200 OK?因为当我查看它时,我看到了 503“服务不可用”。尝试直接浏览example.restdb.io/rest/mock-data,我想至少在那里你会看到同样的东西。因此,如果服务器以 503 响应,您的请求将无法正常工作。我认为您收到 CORS 错误消息的唯一原因是因为许多服务器通常不发送 Access-Control-Allow-Origin 5xx 响应或其他响应。他们只发送成功响应(例如,200 OK)。
  • 不要将 Access-Control-Allow-Origin 添加到您的请求中。该标头严格来说只是一个 response 标头,供服务器在响应中发回给您。将它添加到请求中的唯一效果是破坏事物。与 Access-Control-Allow-Methods 标头相同。将这些添加到您的请求中不会阻止浏览器遇到问题中引用的第一个错误。

标签: javascript reactjs axios


【解决方案1】:
 },
  "proxy": "http://localhost:8080",
  "devDependencies": {

在 package.json 中使用代理

【讨论】:

    【解决方案2】:

    经过很长时间试图弄清楚 CORS 的工作原理。我尝试了很多方法在我的 FE 和 BE 代码中修复它。某些方式出现 CORS 错误,某些方式服务器未收到来自客户端的正文,以及其他错误...

    终于搞定了。我希望这可以帮助某人:

    BE 代码(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 
    
    

    我的 FE 代码(JS):

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

    【讨论】:

      【解决方案3】:

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

      Reason: expected ‘true’ in CORS header ‘Access-Control-Allow-Credentials’

      不要使用

      withCredentials: true
      

      但设置

      'Access-Control-Allow-Credentials':true
      

      在标题中。

      【讨论】:

      • 不使用 withCredentials: true 解决了我的问题.. 但我没有在 req 标头中设置 'Access-Control-Allow-Credentials':true .. 而是我在服务器的 web.config 中添加了这个并解决了问题。
      【解决方案4】:

      我将尝试这个复杂的主题。

      什么是起源

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

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

      这与 CORS 问题有什么关系?

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

      如果您打开网络浏览器并打开一个本地 HTML 文件,并且在该 html 文件中有想要向 google 发出请求的 javascript,您会收到以下错误:

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

      如果我的页面是从 localhost 上的服务器提供的,这同样适用:

      本地主机服务器示例

      如果我们使用以下代码在 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

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

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

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

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

      更多链接

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

      【讨论】:

      • 这是一个非常全面的答案。应该作为一个很好的参考。
      【解决方案5】:

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

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

      但要注意添加 localhost 正确 => 'http://localhost:3000',而不是在末尾添加 '/' => 'http://localhost:3000/',这是我的问题。

      【讨论】:

        【解决方案6】:

        我想每个人都知道 cors 是什么以及它的用途。 以简单的方式,例如如果您使用nodejs和express进行管理,启用它是这样的

        依赖:

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

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

        而对于本地浏览器请求的问题,只需要安装google chrome这个扩展即可。

        名称:允许 CORS:Access-Control-Allow-Origin

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

        这允许您在本地启用和禁用 cros,问题解决了。

        【讨论】:

        • 经过很多方法都行不通。我试图在 cors 选项中添加 origin:"*",它可以工作。太感谢了。你救了我。
        【解决方案7】:

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

        $ npm install cors
        

        然后添加这些行来支持Access-Control-Allow-Origin,

        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'});
        });
        

        您可以实现同样的效果,无需任何外部模块

        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();
        });
        

        【讨论】:

        • @klimqx 下面添加了有关安装 npm 模块和需要它的信息,此答案中缺少这些信息
        【解决方案8】:
        npm i cors
        const app = require('express')()
        app.use(cors())
        

        以上代码对我有用。

        【讨论】:

          【解决方案9】:

          试试代理 package.json 添加代码:

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

          然后重启 npm enjoy

          相同的代码

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

          【讨论】:

          【解决方案10】:

          我在尝试创建 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',
              }
          });
          

          【讨论】:

          • CORS 是一个基于后端的问题,在标头中发送上述参数没有好处。
          【解决方案11】:

          我有同样的错误。我通过使用npm i cors 在我的后端安装 CORS 解决了这个问题。然后,您需要将其添加到您的代码中:

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

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

          【讨论】:

          • 这对我有用,还请注意,您必须在请求之前使用app.use(cors())
          【解决方案12】:

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

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

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

          【讨论】:

            【解决方案13】:
            $ npm install cors
            

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

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

            【讨论】:

              【解决方案14】:

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

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

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

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

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

              【讨论】:

              • 我已经添加了它,'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 端点。
              • 您是否像本例中那样完成了 CORS 的设置? restdb.io/docs/apikeys-and-cors
              • "Access-Control-Allow-Origin" 是响应标头,因此将其添加到请求中并没有任何用处。
              【解决方案15】:

              据我了解,问题是请求是从 localhost:3000 发送到 localhost:8080 的,并且浏览器拒绝了诸如 CORS 之类的请求。所以解决方案是创建代理

              我的解决方案是:

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

              【讨论】:

                【解决方案16】:

                在这种情况下,对请求使用 Access-Control-Allow-Origin 标头对您没有帮助,而此标头只能用于响应...

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

                【讨论】:

                • crossorigin:true 添加到标题对我来说是诀窍。干杯
                猜你喜欢
                • 2014-12-25
                • 2017-06-22
                • 2019-12-20
                • 2020-03-15
                • 2018-09-25
                • 2021-06-17
                • 1970-01-01
                • 2021-08-13
                • 2018-02-26
                相关资源
                最近更新 更多