您的当前位置:首页正文

【Node.js】Express---基于 CORS 解决接口跨域问题详解

2024-11-01 来源:个人技术集锦

一、跨域问题概述

1. 什么是跨域问题?

跨域问题是指浏览器的同源策略限制了网页从不同的域名、协议或端口加载资源。具体来说,当前端试图访问不同于当前页面所在的域时(如 http://localhost:3000 访问 http://api.example.com),浏览器默认会阻止这种请求,这就是常见的跨域问题。

2. CORS 的作用

CORS(Cross-Origin Resource Sharing,跨域资源共享)是浏览器的一项机制,允许服务器声明哪些外域可以访问其资源。通过配置 HTTP 头信息,服务器可以告知浏览器,某些请求是允许的,即使这些请求来自于不同的域名、协议或端口。

二、什么是 CORS 头信息?

CORS 通过一系列的 HTTP 头信息来决定是否允许跨域请求,其中包括:

  • Access-Control-Allow-Origin:指定允许访问资源的源(域、协议、端口)。
  • Access-Control-Allow-Methods:定义允许的 HTTP 方法(如 GETPOST)。
  • Access-Control-Allow-Headers:列出允许的自定义请求头。
  • Access-Control-Allow-Credentials:是否允许携带身份凭证(如 Cookies)。
  • Access-Control-Max-Age:指定预检请求的缓存时间。

了解这些头信息的作用后,我们可以更好地配置跨域策略。

三、Express 中的 CORS 中间件

1. 安装 CORS 中间件

在 Express 中,我们可以通过使用 cors 中间件轻松地处理跨域问题。首先,通过 npm 安装该中间件:

npm install cors

安装完成后,就可以在你的 Express 应用中引入并使用它。

2. 基本用法

在 Express 中使用 cors 非常简单。我们只需将它作为一个全局中间件应用到 Express 应用中,默认情况下,它将允许所有的跨域请求:

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

const app = express();

// 使用 CORS 中间件,允许所有跨域请求
app.use(cors());

app.get('/api/data', (req, res) => {
  res.json({ message: '这是来自 API 的数据' });
});

app.listen(3000, () => {
  console.log('服务器运行在 http://localhost:3000');
});

通过上述代码,我们成功解决了跨域问题,客户端现在可以从任何来源访问 /api/data 接口。

3. 限制允许的域名

虽然默认情况下 CORS 中间件允许所有跨域请求,但在某些场景下,我们可能需要限制允许访问的源。可以通过设置 origin 属性来实现这一点:

const corsOptions = {
  origin: 'http://example.com', // 仅允许来自 http://example.com 的请求
};

app.use(cors(corsOptions));

此时,只有来自 http://example.com 的请求才能成功跨域访问我们的接口,其他域名的请求将被阻止。

四、CORS 的进阶配置

1. 允许多源跨域请求

有时候,我们可能需要允许多个域名访问资源。此时可以将 origin 配置为一个包含多个源的数组:

const corsOptions = {
  origin: ['http://example.com', 'http://another-domain.com'],
};

app.use(cors(corsOptions));

通过这种方式,http://example.comhttp://another-domain.com 都可以跨域访问接口。

2. 允许带凭证的请求

如果客户端需要在跨域请求中发送凭证(如 Cookies 或认证信息),则必须在服务器端启用 credentials

const corsOptions = {
  origin: 'http://example.com',
  credentials: true, // 允许发送凭证
};

app.use(cors(corsOptions));

同时,前端在发起请求时也需要将 withCredentials 选项设置为 true

axios.get('http://api.example.com/data', { withCredentials: true });

这时,浏览器将在请求中携带 Cookies,并且服务器响应头将包含 Access-Control-Allow-Credentials: true

3. 自定义允许的请求方法和头信息

在某些情况下,客户端可能会使用自定义的 HTTP 方法或请求头,例如 PUT 请求或带有自定义认证头的请求。可以通过设置 methodsallowedHeaders 来允许这些自定义的请求方法和头信息:

const corsOptions = {
  origin: 'http://example.com',
  methods: ['GET', 'POST', 'PUT'], // 允许的 HTTP 方法
  allowedHeaders: ['Content-Type', 'Authorization'], // 允许的请求头
};

app.use(cors(corsOptions));

通过这种配置,服务器将允许客户端使用 GETPOSTPUT 方法,以及 Content-TypeAuthorization 请求头。

4. 配置预检请求的缓存时间

浏览器在发送某些复杂请求(如带有自定义头或非简单方法的请求)之前,会先发送一个 OPTIONS 请求来“预检”服务器是否允许该请求。这种预检请求可能会增加额外的网络开销。通过 maxAge 配置,我们可以指定预检请求的缓存时间,以减少频繁的预检请求:

const corsOptions = {
  origin: 'http://example.com',
  maxAge: 600, // 预检请求的缓存时间,单位为秒
};

app.use(cors(corsOptions));

在上述配置中,浏览器将在 10 分钟内缓存预检结果,从而减少不必要的请求。

五、CORS 中可能遇到的常见问题

1. 缺少 CORS 头信息

有时在配置完 CORS 中间件后,前端仍然会报错,提示缺少 CORS 头信息。这通常是由于未正确应用 CORS 中间件,或者中间件的位置不正确。确保 app.use(cors()) 在所有路由之前调用。

2. OPTIONS 请求返回 404

某些复杂请求会先发起 OPTIONS 预检请求,如果服务器没有正确处理 OPTIONS 请求,可能会返回 404 错误。解决办法是在 Express 中为 OPTIONS 请求设置统一处理逻辑:

app.options('*', cors()); // 处理所有的 OPTIONS 请求

3. 跨域请求带凭证报错

当启用了 credentials 选项时,Access-Control-Allow-Origin 不能为 *,而必须指定具体的域名。这是因为安全考虑,浏览器不允许带凭证的跨域请求使用通配符。

六、总结

通过本文的介绍,我们详细讲解了如何在 Express 中通过 CORS 中间件解决跨域问题。从基本的全局配置到复杂的多源和自定义请求方法设置,我们可以灵活地应对各种跨域请求场景。CORS 是确保前后端数据交互顺利进行的重要工具,合理配置 CORS 可以有效提升应用的安全性和性能。

推荐:

  • JavaScript
  • react
  • vue

显示全文