如何允许CORS?

mik*_*ong 609 node.js cors coffeescript express

我试图在我的Node.js应用程序中支持使用Express.js Web框架的CORS.我已经阅读有关如何处理此问题的Google小组讨论,并阅读了一些有关CORS如何工作的文章.首先,我这样做了(代码是用CoffeeScript语法编写的):

app.options "*", (req, res) ->
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  # try: 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
  # try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...
Run Code Online (Sandbox Code Playgroud)

它似乎不起作用.好像我的浏览器(Chrome)没有发送初始OPTIONS请求.当我刚刚更新资源块时,我需要将跨源GET请求提交到:

app.get "/somethingelse", (req, res) ->
  # ...
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...
Run Code Online (Sandbox Code Playgroud)

它有效(在Chrome中).这也适用于Safari.

我读过......

在实现CORS的浏览器中,每个跨源GET或POST请求前面都有一个OPTIONS请求,用于检查GET或POST是否正常.

所以我的主要问题是,为什么在我的案例中似乎没有发生这种情况?为什么我的app.options块没有被调用?为什么我需要在主app.get块中设置标题?

Way*_*rer 643

我发现最简单的方法是使用node.js包cors.最简单的用法是:

var cors = require('cors')

var app = express()
app.use(cors())
Run Code Online (Sandbox Code Playgroud)

当然,有很多方法可以根据您的需要配置行为; 上面链接的页面显示了许多示例.

  • 你还需要设置`cors({credentials:true,origin:true})` (48认同)
  • 当我将它与凭据一起使用时,它对我来说失败了。:( 其他一切都像魅力一样工作..但如果它在 Credentials 设置为 true 时失败,对我来说就没用了 (2认同)
  • 如何在此处启用选项预检? (2认同)

evi*_*ery 427

尝试将控制权传递给下一个匹配的路线.如果Express首先匹配app.get路由,那么它将不会继续进入选项路由,除非你这样做(注意使用next):

app.get('somethingelse', function(req, res, next) {
    //..set headers etc.

    next();
});
Run Code Online (Sandbox Code Playgroud)

在组织CORS的方面,我把它放在一个适合我的中间件中:

//CORS middleware
var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', 'example.com');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');

    next();
}

//...
app.configure(function() {
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({ secret: 'cool beans' }));
    app.use(express.methodOverride());
    app.use(allowCrossDomain);
    app.use(app.router);
    app.use(express.static(__dirname + '/public'));
});
Run Code Online (Sandbox Code Playgroud)

  • `config.allowedDomains`是逗号分隔的字符串还是数组? (21认同)
  • config.allowedDomains应该是一个空格分隔的数组 (2认同)

Dob*_*eer 156

要回答您的主要问题,如果POST或GET中包含任何非简单内容或标题,则CORS规范仅要求OPTIONS调用在POST或GET之前.

需要CORS pre-flight请求的内容类型(OPTIONS调用)是除以下内容之外的任何Content-Type :

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain

除上述内容之外的任何其他内容类型都将触发飞行前请求.

至于标题,除以下内容之外的任何请求标题都会触发飞行前请求:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type
  5. DPR
  6. Save-Data
  7. Viewport-Width
  8. Width

任何其他请求标头将触发飞行前请求.

因此,您可以添加自定义标头,例如:x-Trigger: CORS,这应该触发飞行前请求并点击OPTIONS块.

请参阅MDN Web API参考 - CORS预检请求

  • 你能提供一个例子吗? (9认同)
  • 但总的来说,仅限链接的答案是脆弱的,因为它们随时都可能被打破.也就是说,这个答案看起来很好,因为它突出了"OPTIONS"块不发送的一般条件.如果它有接受的`HEADERS`列表,或者`content-types`需要`OPTIONS`等等,那会很好但是这是一个好的开始 (5认同)
  • 我链接的页面似乎有很多例子.你能告诉我你认为缺少什么样的例子吗? (3认同)

小智 112

保持路由的相同想法.我用这个代码:

app.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});
Run Code Online (Sandbox Code Playgroud)

http://enable-cors.org/server_expressjs.html示例类似

  • 预检怎么样? (4认同)

Yat*_*ngh 81

npm install cors --save
Run Code Online (Sandbox Code Playgroud)

并在您的主文件中添加这些行,您的请求将继续(在任何路由之前保留它).

const cors = require('cors');
const express = require('express');
let app = express();
app.use(cors());
app.options('*', cors());
Run Code Online (Sandbox Code Playgroud)

  • `app.options('*',cors())`//在其他路由之前包含 (3认同)

mcf*_*edr 49

我已经制作了一个更完整的中间件,适合快递或连接.它支持OPTIONS预检检查请求.请注意,它允许CORS访问任何内容,如果要限制访问,可能需要进行一些检查.

app.use(function(req, res, next) {
    var oneof = false;
    if(req.headers.origin) {
        res.header('Access-Control-Allow-Origin', req.headers.origin);
        oneof = true;
    }
    if(req.headers['access-control-request-method']) {
        res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
        oneof = true;
    }
    if(req.headers['access-control-request-headers']) {
        res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
        oneof = true;
    }
    if(oneof) {
        res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
    }

    // intercept OPTIONS method
    if (oneof && req.method == 'OPTIONS') {
        res.send(200);
    }
    else {
        next();
    }
});
Run Code Online (Sandbox Code Playgroud)


小智 35

安装expressjs的cors模块.你可以按照这些步骤>

安装

npm install cors
Run Code Online (Sandbox Code Playgroud)

简单用法(启用所有CORS请求)

var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请访问https://github.com/expressjs/cors

  • ```TypeError:无法读取undefined```的属性'headers'最基本的应用程序设置. (2认同)

Rus*_*uss 30

做这样的事情:

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();
});
Run Code Online (Sandbox Code Playgroud)


小智 18

在不同端口中使用express + node + ionic运行完成测试.

Localhost:8100

Localhost:5000

// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests

app.all('*', function(req, res, next) {
       res.header("Access-Control-Allow-Origin", "*");
       res.header("Access-Control-Allow-Headers", "X-Requested-With");
       res.header('Access-Control-Allow-Headers', 'Content-Type');
       next();
});
Run Code Online (Sandbox Code Playgroud)

  • 我们需要在哪个文件中添加这行? (2认同)

小智 18

首先只需在项目中安装cors.将终端(命令提示符)cd带到项目目录并运行以下命令:

npm install cors --save
Run Code Online (Sandbox Code Playgroud)

然后获取server.js文件并更改代码以在其中添加以下内容:

var cors = require('cors');


var app = express();

app.use(cors());

app.use(function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   next();
});
Run Code Online (Sandbox Code Playgroud)

这对我有用..

  • 如果你正在做`res.header`的话,你不需要`cors`.`cors`是一个为你处理所有这些的库.删除你的第一行和第三行(用'cors`来解决所有问题),你会发现它仍然有效. (3认同)

Kik*_*ijo 9

这对我来说很有用,因为它在路线中很容易实现,我使用meanjs和它的工作正常,safari,chrome等.

app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){ 
        res.header('Access-Control-Allow-Origin', '*'); 
        res.header('Access-Control-Allow-Methods', 'GET, POST');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
        return res.send(200);

    });
Run Code Online (Sandbox Code Playgroud)


Shu*_*rma 9

前段时间,我遇到了这个问题所以我这样做是为了在我的nodejs app中允许CORS:

首先,您需要 cors使用以下命令进行安装:

npm install cors --save
Run Code Online (Sandbox Code Playgroud)

现在将以下代码添加到您的应用程序启动文件中,如(app.js or server.js)

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

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));

require('./router/index')(app);
Run Code Online (Sandbox Code Playgroud)


Mil*_*bar 8

corspackage 是解决express.js 中 CORS 策略问题的推荐方法,但您还需要确保也启用它app.options,如下所示:

const cors = require('cors');

// enable cors
app.use(
  cors({
    origin: true,
    optionsSuccessStatus: 200,
    credentials: true,
  })
);
app.options(
  '*',
  cors({
    origin: true,
    optionsSuccessStatus: 200,
    credentials: true,
  })
);
Run Code Online (Sandbox Code Playgroud)


Kor*_*men 6

如果您想使控制器特定,您可以使用:

res.setHeader('X-Frame-Options', 'ALLOWALL');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
Run Code Online (Sandbox Code Playgroud)

请注意,这也将允许iframe.


Gad*_*ema 6

可以参考下面的代码。来源:Academind/node-restful-api

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

//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
    res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
    );
    if(req.method === 'OPTIONS'){
        res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
        return res.status(200).json({});
    }
    next(); //so that other routes can take over
})
Run Code Online (Sandbox Code Playgroud)


vka*_*v15 6

最简单的答案是只使用cors 包

const cors = require('cors');

const app = require('express')();
app.use(cors());
Run Code Online (Sandbox Code Playgroud)

这将全面启用 CORS。如果您想学习如何在没有外部模块的情况下启用 CORS,您真正需要的只是一些设置“Access-Control-Allow-Origin”标头的Express 中间件。这是允许从浏览器到服务器的交叉请求域所需的最低限度。

app.options('*', (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  res.send('ok');
});

app.use((req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
});
Run Code Online (Sandbox Code Playgroud)


Bal*_*han 5

在我的index.js补充中:

app.use((req, res, next) => {
   res.header("Access-Control-Allow-Origin", "*");
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
   next();
}) 
Run Code Online (Sandbox Code Playgroud)

  • 我应该评论说“Access-Control-Allow-Origin = *”意味着您将无法将 Cookie 发送到服务器,它们将被 CORS 策略拒绝 - 来源:https://developer.mozilla.org /en-US/docs/Web/HTTP/CORS#Requests_with_credentials 。因此,如果您想使用 cookie,请不要使用此选项。 (2认同)