【问题标题】:Nodejs Express CORS issue with 'Access-Control-Allow-Origin''Access-Control-Allow-Origin' 的 Nodejs Express CORS 问题
【发布时间】:2017-10-24 01:04:25
【问题描述】:

我正在尝试使用 Angular 1、Nodejs 和 Express 创建单页应用程序。我正在使用 Angular 的 $http post 功能发布一个请求,在该请求中我将请求中的标头值传递给 API 端点。

我在 Chrome 中遇到错误消息:

XMLHttpRequest cannot load 
http://localhost:7878/EIAMIDSupportREST/EIAMIDSupport/updateEIAMID. The 
value of the 'Access-Control-Allow-Origin' header in the response must not 
be the wildcard '*' when the request's credentials mode is 'include'. Origin 
'http://localhost:3000' is therefore not allowed access. The credentials 
mode of requests initiated by the XMLHttpRequest is controlled by the 
withCredentials attribute.

使用此请求正文:

HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,PUT,POST,PATCH,DELETE
Access-Control-Allow-Headers: Content-Type
Allow: POST
Content-Type: text/html; charset=utf-8
Content-Length: 4
Date: Tue, 23 May 2017 23:32:15 GMT
Connection: keep-alive

为了解决 CORS 问题,我已经 npm 安装了 cors 库。

在我的 app.js 中,我添加了以下几行:

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

这是我的完整 app.js:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');

var cons = require('consolidate');
//enable CORS 
var cors = require('cors');
var app = express();
app.use(cors({ origin: 'http://localhost:3000' , credentials :  true,  methods: 'GET,PUT,POST,OPTIONS', allowedHeaders: 'Content-Type,Authorization' }));
// view engine setup
app.engine('html', cons.swig)
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'html');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

这是我的 index.html 页面

<html>
<head>
<script 

src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript">
var app = angular.module("app", []);
   app.controller("HttpGetController", function ($scope, $http) {
       $scope.SendData = function () {
         var req = {
          method: 'POST',
          url: 'http://localhost:7878/EIAMIDSupportREST/EIAMIDSupport/updateEIAMID',
          withCredentials: true,
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Authorization': 'Basic user:password'
          }
         }
         $http(req)
           .then(function(data, status, header, config)
             {
               $scope.PostDataResponse = data,
               console.log($scope.PostDataResponse);
             })
             .catch(function(data, status, header, config)
             {
                $scope.PostDataResponse = data,
                console.log($scope.PostDataResponse);
             });

       };

     });
</script>
</head>
<body>
  <div ng-app="app">
    <div ng-controller="HttpGetController">
      <button  ng-click="SendData()" >Link Accounts</button>
      <hr />AND THE RESPONSE IS:{{ PostDataResponse }}
    </div>
  </div>
</body>
</html>

但是还是不行。

谁能告诉我需要如何以及在哪里更新我的代码以修复“Access-Control-Allow-Origin”通配符问题?

【问题讨论】:

  • 我尝试了你的建议,但我仍然得到同样的错误:
  • 在 app.js 我改变了 - app.use(cors());使用 app.use(cors({ origin: 'localhost:3000' }));反而。重新启动我的节点服务器,仍然收到相同的错误。我做错了什么?

标签: javascript node.js express http-headers cors


【解决方案1】:

虽然@muratgozel 的回答部分正确,但让我更深入地了解 CORS 以及导致问题的原因。当您的浏览器发送跨域响应时,它会在标题中给出它的 Origin 。服务器响应还提供了一个名为 Access-Control-Allow-Origin 的标头。当您在 express 应用程序中使用实例化 'cors' 模块时,Access-Control-Allow-Origin 标头设置为 '*' 通配符,这基本上意味着此服务器资源(快递应用程序的)是公共的并且可以可以从任何地方的任何代码访问,但是此通配符的限制是请求中不允许某些请求标头(例如 Authorization)。您对 index.html 页面的请求有一组 headers 。您应该查看标题,或者您可以简单地按照@muratgozel 所说的操作并使用特定来源实例化 cors 除了将凭据选项设置为 true

app.use(cors({ origin: 'http://example.com' , credentials :  true}));

【讨论】:

  • 我尝试了你的建议并用 app.use(cors({ origin: 'localhost:3000' , credentials : true, methods: 'GET,PUT,POST,OPTIONS', allowedHeaders: 'Content-Type,Authorization' }));但是,在 chrome 检查器中,我的更改似乎没有生效。我错过了什么?请帮忙:)
  • 阅读上面的答案,它似乎是正确的。您可以使用您收到的确切错误消息添加对原始问题的编辑吗?也许还有 node.js 代码?信息越多越好。
  • 关于 cors 问题的最佳答案
  • 拯救了我的一天!没有看到提到这个credentials : true 选项并且解释很好。谢谢!
【解决方案2】:

还有一个选项可以将origin 设置为true 以反映由req.header('Origin') 定义的请求来源。

app.use(cors({ origin: true, credentials: true }));

【讨论】:

    【解决方案3】:

    您的 cors 包有一个 origin 选项,它会更改“Access-Control-Allow-Origin”标头。

    指定启动 cors() 函数的来源选项:

    app.use(cors({ origin: 'http://example.com' }));
    

    还有更多详情the cors package npm page

    【讨论】:

      【解决方案4】:

      以防万一有人想使用基于纯 JavaScript 的解决方案,下面是在我的 Google Chrome (80)、Mozilla Firefox (72) 和 Microsoft Edge 浏览器上运行的代码。

      开发平台

      我正在使用 NodeJS (12) 开发一个小型分布式 REST API。如果这组服务部署在同一台机器上,则使用不同的端口号来分隔它们。

      另一方面,几个前端应用程序应该同时与许多服务交互。所以,我开始在集成阶段遇到这个 CORS 错误。我为javascript找到的解决方案如下。

      服务器端代码

      在这里,诀窍很简单。您只想在每个响应中添加以下行

      res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4000');

      res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept');

      res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

      注意:res 是 HTTP 响应对象。

      客户端代码

      在这种情况下,请求将照常进行编码。我们唯一需要知道的是,在我们要发送的每个请求之前,浏览器将首先使用 HTTP "OPTIONS" 方法发送 preflight 请求。 这个 preflight 请求将根据其内部 CORS 策略告诉浏览器是否会收到您原始请求的答案。

      在这个例子中,我只是使用 POST 方法发送一个 JSON 对象:

      var xhr = new XMLHttpRequest();

      xhr.open(method, requestUrl);

      xhr.setRequestHeader('Content-type', 'text/plain');

      OPTIONS 方法响应处理程序

      为了相应地处理 OPTIONS 请求,您必须在服务器端进行如下检查:

      if (req.method.toLowerCase() == 'options')

      res.writeHead(200);

      就是这样,没有额外的麻烦。

      代币

      当您需要通过标头发送令牌时,您必须将“令牌”添加到您的“选项”响应中,如下所示:

      res.setHeader('Access-Control-Allow-Headers', 'Content-Type, token');

      更多信息

      https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

      【讨论】:

        猜你喜欢
        • 2021-05-12
        • 2016-09-20
        • 2014-11-20
        • 2016-09-30
        • 1970-01-01
        • 2019-02-06
        • 2017-11-21
        • 2019-06-17
        • 2017-12-11
        相关资源
        最近更新 更多