如何在Node.js中用Express使用CORS

2,138 阅读6分钟

如何在Node.js中用Express使用CORS

Node.js是一个开源的、跨平台的运行时间,当在服务器端执行JavaScript代码时使用。其中一个流行的Node.js服务器框架是Express。在Node.js中实现CORS有助于你访问浏览器上的众多功能。

Express允许你配置和管理一个HTTP服务器来访问同一域的资源。

构成一个原点的三个部分是protocal、域和端口。

The CORS origin concept

今天,有许多应用程序依赖API来访问不同的资源。一些流行的API包括天气、时间和字体。也有一些服务器托管这些API,并确保信息被传递到网站和其他终端。因此,进行跨源调用,是现代网络应用的一个流行用例。

比方说,从另一个服务器访问图片、视频、iframe或脚本。这意味着网站正在从不同的来源或域中访问资源。当建立一个应用程序来用Express提供这些资源时,对这种外部来源的请求可能会失败。这就是 CORS 处理跨源请求的地方。

目标

本指南将帮助你学习如何用 Express 配置 CORS。

前提条件

要跟上这篇文章,必须具备Node.jsExpress的知识。

什么是 CORS?

CORS 是Cross-Origin Resource Sharing 的缩写。它允许我们放松应用于 API 的安全性。这是通过绕过Access-Control-Allow-Origin 头信息来实现的,该头信息指定了哪些origins 可以访问 API。

换句话说,CORS是一个浏览器的安全功能,它限制了与其他服务器的跨源HTTP请求,并指定哪些域可以访问你的资源。

CORS如何工作

一个API是两个程序进行通信的一套程序。这意味着API资源被其他客户和服务器所消耗。

这里有两种情况。

The CORS same-origin concept

客户端和服务器有相同的来源。在这个例子中,访问资源将是成功的。你试图访问你服务器上的资源,同一个服务器处理这个请求。

The CORS cross-origin concept

客户端和服务器彼此有不同的起源,即从不同的服务器访问资源。在这种情况下,试图向其他服务器上的资源提出请求将失败。

这对浏览器来说是一个安全问题。CORS的作用是禁用这一机制,允许访问这些资源。CORS将添加一个响应头access-control-allow-origins ,并指定哪些来源是允许的。CORS确保我们发送的是正确的标头。

因此,一个处理公共API的公共服务器将在响应中添加一个与CORS相关的头。客户端机器上的浏览器将查看这个头,并决定是否可以安全地将该响应传递给客户端。

用 Express 设置 CORS

让我们创建一个非常基本的 Express HTTP 服务器端点,提供一个 GET 响应。

确保你已经安装了Node.js runtime 并运行npm init -y 来启动你的简单 Express 服务器项目。要在 Node.js 应用程序中使用 CORS,你需要 Node.js NPM 注册处提供的cor package 。继续使用下面的命令,将 CORS 与下列其他软件包一起安装。

npm i cors express nodemon

创建一个简单的Express GET请求

下面是一个简单的index.js express服务器。

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

    const ingredients = [
    {
        "id": "1",
        "item": "Bacon"
    },
    {
        "id": "2",
        "item": "Eggs"
    },
    {
        "id": "3",
        "item": "Milk"
    },
    {
        "id": "4",
        "item": "Butter"
    }
];

app.get('/ingredients', (req, res) =>{
    res.send(ingredients);
});
app.listen(6069);

上面的代码描述了一个使用Express的简单HTTP服务器。

npm nodemon 运行服务器。在你的浏览器上导航到http://localhost:6069/ingredients 。你将会得到这些成分的文本项目。

在这个例子中,跨源是允许的,因为你目前在同一个域名上,而且你是在同一个域名上执行这个请求。

现在让我们尝试使用fetch命令来获取这些成分。

我将执行同样的请求,但从另一个网站执行。在这种情况下,我使用https://www.section.io

在你的浏览器上打开https://www.section.io ,使用Fetch API从浏览器的控制台执行下面的获取请求。

fetch("http://localhost:6069/ingredients").then(req => req.text()).then(console.log)

在执行上述请求之前,请确保服务器已经启动并运行。

我们正在从另一个起源域获取成分信息。这个URL的原点是不允许从这个服务器接收这个响应的。因此,它将抛出下面的 CORS 错误。

CORS policy error

为了解决这个错误,我们需要在服务器上添加 CORS 标头,让https://www.section.io 访问服务器的响应。

在你的index.js 文件中包括以下内容。

const cors = require('cors');
app.use(cors({
    origin: 'https://www.section.io'
}));

如果你现在执行fetch命令,它应该可以正常工作。

然而,如果从另一个网页发出获取请求,它将会失败并抛出以下错误。

Cors policy header error

这意味着你只能访问我们服务器的资源。你可以有一个数组,如下图所示,这些多源的资源。

const cors = require('cors');
app.use(cors({
    origin: ['https://www.section.io', 'https://www.google.com/']
}));

尽管如此,该API可以是公开的,任何跨源的API和服务器都可以访问这些资源。下面的代码块将确保任何页面都可以访问配料资源。

app.use(cors({
    origin: '*'
}));

Asterisk符号将创建CORS头,因此,任何原点都可以获得这个localhost服务器的响应。

由于这里没有定义具体的起源,app.use(cors()) 也会完成这个任务。

你也可以有动态原点。这些是白名单上的起源,可以访问你的API。这可以用来从数据库中提取资源。

比方说,你有不同的账户,即开发者账户,你可能希望他们能够访问API。要有这种动态白名单,使用这个origin函数,它可以单独返回这些域。

const whitelist = ['http://developer1.com', 'http://developer2.com']
const corsOptions = {
  origin: (origin, callback) => {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error())
    }
  }
}

执行更多请求

一个Express服务器有许多管理CORS的具体方法,以确定哪些其他服务器和API可以被访问。

例如,一个服务器是由几个方法组成的。然而,并不是每个方法都应该暴露给其他起源。因此,在 CORS 中间件中,你可以指定哪些方法可以被 CORS 策略所访问。

这些方法包括GET,POST,DELETE,UPDATE, 和OPTIONS

app.use(cors({
    methods: ['GET','POST','DELETE','UPDATE','PUT','PATCH']
}));

你甚至可以指定你的服务器的哪些路由可以被访问。

app.get('/ingredients', cors(), (req, res, next) => {
    res.send(ingredients);
});

使用案例

假设你正在使用React来构建一个前端应用程序。最终,你会把它连接到一个后端API。如果没有设置 CORS,该应用程序可能会遇到问题。原因很简单,因为前端和后端都来自彼此不同的源头。

CORS与API是相辅相成的。CORS的一个很好的使用场景是开发RESTful APIs时。例如,创建一个Node.js RESTful API,类似于这个使用PostgresSQL和Express的Node.js RESTful Web API

总结

当你在服务器上部署一个应用程序时,你不应该接受来自每个域的请求。相反,你应该指定哪些来源可以向你的服务器发出请求。

这样,你就能够阻止那些试图克隆你的网站或从未经授权的服务器发出请求的用户。这是一项重要的安全措施。检查这个CORS NPM 注册表,了解更多关于在你的 Express 应用程序中使用 CORS 的地方。