来自来源的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】来自来源的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头【英文标题】:XMLHttpRequest at from origin has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource 【发布时间】:2020-12-13 18:23:16 【问题描述】:

我遇到了 REST API 的问题。我的前端在 React 中,API 在 Express 中。我间歇性地低于错误。我浏览了许多其他类似的帖子,并尝试将 HTTP 标头添加到响应中,但没有任何运气。这些调用在 Postman 客户端上运行良好。

“来自 'http://localhost:3000' 的来源已被 CORS 策略阻止: 请求中不存在“Access-Control-Allow-Origin”标头 资源。”

到目前为止,我已经添加了以下几行来填充 HTTP 响应。最烦人的部分是这些错误只发生在某些 Web 服务而不是其他 Web 服务中。它们都是相同的编码,因此很难确定为什么在某些情况下它会失败。

我的 server.js(Express REST 应用程序)如下...

 const express = require('express');


const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const controllers = require('./controllers');

const logger = require('./logger/logger');
const port = 9000;

app.use(bodyParser.urlencoded( extended: true ))
app.use(bodyParser.json());
app.use(bodyParser.raw());
controllers.init(app);
app.use(cors());


//Listen server on define port
var server = app.listen(port, () => 
  
    logger.info("API Server is running on port " + port);
)

所以,到目前为止,我注意到的是,当我在控制器中添加以下部分以包含 HTTP 响应标头时(控制器使用服务和模型来服务请求),即使我在第一次成功调用后删除它们,错误也会消失来自我的 React 前端,这真的很奇怪。我使用 Chrome 来测试我的 React 前端。这是否意味着 Chrome 浏览器正在缓存一些东西。当谈到起源?我担心这将如何在生产中跨越?有没有人经历过这种行为?

app.use((req, res, next) => 
        res.append('Access-Control-Allow-Origin', "*");
        res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
        res.append('Access-Control-Allow-Headers', 'Content-Type');
        next();
    );

以下是我用于 Express API 服务器的包。我的 React 前端使用 "react": "^16.13.1"

"dependencies": 
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "express": "^4.17.1",

【问题讨论】:

尝试在您的Access-Control-Allow-Methods 中添加OPTIONSres.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); 谢谢郝,只是没有运气。虽然一个有趣的观察是,我试图清除 Chrome 的缓存,当我重新加载我的页面时,所有 API(所有 HTTP GET 调用)都出现了同样的错误。这进一步证明了 Chrome 正在为每个 URI 的某个地方缓存这些标头,只要它从缓存中获取它就不会抱怨。 Chrome 有一个插件可以避免 CORS,但我不想走这条路,因为我不能指望所有最终用户都安装一个插件来解决这个问题。这是一个超级烦人的问题... 好吧,您可以尝试使用 API 测试工具,例如 PostMan,看看究竟是什么导致了这个问题。检查响应标头等中是否缺少任何内容。这可能会有所帮助。 我已经尝试过了(根据我最初的问题),即从 Postman 调用这个 GET API 没有问题。它似乎在 React 页面中不起作用。 【参考方案1】:

好的,只是通过添加以下部分来完成这项工作

controllers.init = function (app) 
            app.use((req, res, next) => 
                res.append('Access-Control-Allow-Origin', '*');
                res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
                res.append('Access-Control-Allow-Headers', 'Content-Type');
                next();
            );

在我的控制器文件夹下的 index.js 中。 index.js 包含所有其他控制器的初始化......见下文

(function (controllers) 
    var appMenuController = require("./appMenuController");
    var applicantTypeController = require("./applicantTypeController");
    var permitApplicationController = require("./permitApplicationController");
    var campusController = require("./campusController");
    var paymentMethodController = require("./paymentMethodController");
    var permitTypeController = require("./permitTypeController");
    var permitController = require("./permitController");
    var permitChangeRequestController = require("./permitChangeRequestController");
    var requestTypeController = require("./requestTypeController");
    var vehicleController = require("./vehicleController");
    
    controllers.init = function (app) 
        app.use((req, res, next) => 
            res.append('Access-Control-Allow-Origin', '*');
            res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
            res.append('Access-Control-Allow-Headers', 'Content-Type');
            next();
        );
        appMenuController.init(app);
        applicantTypeController.init(app);
        permitApplicationController.init(app);
        campusController.init(app);
        paymentMethodController.init(app);
        permitTypeController.init(app);
        permitController.init(app);
        permitChangeRequestController.init(app);
        requestTypeController.init(app);
        vehicleController.init(app)
    
)(module.exports);

我仍然不明白,即为什么 Chrome(甚至 Firefox)不允许在同一主机(即 localhost)上的 2 个 localhost 之间进行 HTTP REQ\RESP 通信。来自本地主机的响应中的威胁在哪里?除非我误解了 CORS

【讨论】:

以上是关于来自来源的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

从源“http://localhost:3000”访问“https://***”处的 XMLHttpRequest 已被 CORS 策略阻止

XMLHttpRequest 无法加载 URL。 Access-Control-Allow-Origin 不允许的来源

访问 XMLHttpRequest 时访问 XMLHttpRequest 已被 CORS 策略阻止

AngularJs——对 XMLHttpRequest 的访问已被 CORS 策略阻止 [重复]

如何修复 XMLHttpRequest 已被 CORS 策略阻止

Flutter - XMLHttpRequest 已被 CORS 策略阻止