Node.js 处理跨域有哪几种方式?3 种完整写法一次讲清

编程狮(w3cschool.cn) 2026-09-30 07:04:44 浏览数 (26)
反馈

Node.js 处理跨域三种方式封面

Node.js 处理跨域最干净的做法是在 HTTP 响应里加上 CORS 相关的几个响应头,明确告诉浏览器“允许这次跨域请求”。用 Express 框架的话直接挂一个 cors 中间件即可;开发调试阶段,也可以用代理转发把跨域变成同源,绕开浏览器的同源限制。今天这篇文章,编程狮就把这三种写法从最小示例讲到边界,让你按自己的技术栈直接选对路径。

本文基于 Node.js 16 LTS 与 Express 4 验证,覆盖原生响应头、cors 中间件和代理转发三条路径,并附上横向对比和排错清单。读完你能根据自己用的是原生 http 还是 Express,直接选出最合适的那种,也不再被控制台里的跨域报错吓住。下面先把结论放出来。

先看结论

跨域不是 Node.js 的错,而是浏览器的同源策略在拦截。Node.js 处理跨域有哪几种方式,本质按你的技术栈来定:

你的场景 推荐方式 一句话理由
用原生 http 模块、想完全可控 手动设置 CORS 响应头 不引入额外依赖
用 Express 框架 挂载 cors 中间件 一行搞定,配置灵活
仅本地开发调试 代理转发 不碰响应头,最省事

Node.js 跨域三种处理方式怎么选?

如果你还没装 Express 或想先补 Node.js 基础,建议过一遍 Node.js 基础教程,把 http 服务和中间件概念先铺平。

一、方法一:原生 http 手动设置 CORS 响应头

最底层的方式,是在响应对象上用 setHeader 写入 CORS 相关的几个头。核心是 Access-Control-Allow-Origin,它声明哪些来源被允许。

const http = require('http');

const server = http.createServer((req, res) => {
  // 允许任意来源(生产环境应改成具体域名)
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
  res.end('来自 Node.js 的跨域响应');
});

server.listen(3000, () => console.log('服务在 3000 端口启动'));

上面这段做了三件事:允许来源、允许的方法、允许的请求头。浏览器收到这些头后就会放行跨域请求。

适用场景:当你用原生 http 模块、不想引入任何框架或中间件时,手写响应头最可控。所有 CORS 逻辑都掌握在自己手里。

边界说明:这种方式对预检(OPTIONS)请求也要同样返回这些头。很多初学者只在正常 GET/POST 上设头,结果浏览器先发的 OPTIONS 探路请求没有带头,预检失败,正式请求被拦。

⚠️ 注意:Access-Control-Allow-Origin 设成 * 时不能和 withCredentials 的带 cookie 请求共用,否则浏览器会拒绝。需要身份凭证时,这里必须写明确的域名。

二、方法二:Express 挂载 cors 中间件

如果你用的是 Express,手写响应头就太累了。社区维护的 cors 中间件一行就能开启,还能精细控制允许的来源和方法。

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

const app = express();
app.use(cors()); // 默认允许所有来源

app.get('/api/hello', (req, res) => {
  res.json({ msg: '编程狮 hello' });
});

app.listen(3000, () => console.log('服务在 3000 端口启动'));

预期输出(未在本机执行,依据 cors 中间件官方用法):访问 /api/hello 时,响应头自动带上 Access-Control-Allow-Origin: *,前端跨域请求成功拿到 JSON。需要限定来源时,把 app.use(cors()) 换成 app.use(cors({ origin: 'https://www.w3cschool.cn' })) 即可。写接口时想随时查参数,可翻 Node.js 速查手册。

验证要点:用浏览器打开前端页面发起请求,在开发者工具的 Network 面板里看响应头是否含 Access-Control-Allow-Origin;有则放行,没有则继续按排错清单查。

性能与依赖:cors 中间件只做一次请求头处理,开销极小。它的价值在“可配置”——按路由、按来源、按方法分别放行,比手写 setHeader 更不容易出错。

三、方法三:代理转发绕过跨域

前两种都是在服务端“说服”浏览器放行,而代理转发的思路完全不同:让前端请求打到同源的开发服务器,再由开发服务器把请求转发到真正的后端。对浏览器来说全程同源,根本不存在跨域。

// vite.config.js(开发服务器代理示例)
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true
      }
    }
  }
};

代理转发如何把跨域请求变成同源

适用场景:本地联调阶段最省事。前端代码里直接写 /api/hello(同源),由 Vite 或 webpack-dev-server 转发出去,你完全不用碰 CORS 头。

边界说明:这类代理只跑在开发服务器上,不能进生产环境。生产要么后端正确配置 CORS,要么用 Nginx 反向代理把前后端合成同源,思路一致、实现不同。

四、三种方式横向对比与边界

方式 依赖 适合阶段 可控性
手动 CORS 响应头 无 原生 http 项目 最高
cors 中间件 cors 包 Express 项目 高
代理转发 开发服务器 本地开发 中(仅开发期)

排错清单:

  • 现象:控制台报 No 'Access-Control-Allow-Origin',原因:服务端没返回该头,修复:按方法一、二补上;
  • 现象:带 cookie 仍被拦,原因:* 与凭证冲突,修复:改成具体域名并加 Allow-Credentials;
  • 现象:OPTIONS 预检失败,原因:没允许对应方法和头,修复:在响应头补齐 Allow-Methods 与 Allow-Headers。

💡 小提示:想直接动手试,文末「延伸学习」已放好 Express 教程入口,本地起一个服务就能复现上面的跨域现象。

实操清单:前置、操作、验证与失败处理

按这份清单把跨域跑通:

  • 前置(安装/配置):本机装好 Node.js 16+,Express 项目里 npm install cors 把中间件装上;原生 http 项目则无需任何依赖。
  • 操作(命令/运行):保存示例为 server.js,在终端执行命令 node server.js 启动服务,监听 3000 端口。
  • 验证(检查/预期):用带跨域的前端页面请求接口,预期在 Network 面板看到响应头含 Access-Control-Allow-Origin,请求成功返回 JSON。
  • 失败处理(失败/修复):若仍报跨域,先确认 OPTIONS 预检也被返回了对应头;带凭证时把 * 改成具体域名并加 Allow-Credentials。

总结

Node.js 处理跨域有三条主路径:原生 http 手动写 CORS 响应头、Express 挂 cors 中间件、开发期用代理转发。Node.js 处理跨域有哪几种方式,答案就在“说服浏览器放行”还是“根本不让它意识到这是跨域”这一念之间。本质是同一件事——要么说服浏览器放行,要么根本不让它意识到这是跨域。

要点带走:

  • 用 Express,首选 cors 中间件,配置最省心;
  • 生产环境 Allow-Origin 别图省事写 *,按域名精确放行;
  • 带身份凭证时不能用 *,必须写明确来源并开启凭证;
  • 本地联调最省事的是代理转发,但它只在开发期有效。

下一步建议把浏览器的同源策略和预检机制搞清楚,理解“为什么 OPTIONS 会先飞一次”,排错时你就能精准定位是哪一层拦的。

延伸学习

想把跨域这块彻底理顺,可以按这个顺序来:

  1. 先过一遍 Node.js 入门课程,把 http 服务和中间件基础铺平;
  2. 写接口时翻 Express 教程 查路由与中间件用法;
  3. 想弄懂浏览器为什么拦,这篇 跨域 CORS 是什么 从原理讲到报错,值得延伸阅读。

常见问题

Q:Access-Control-Allow-Origin 设成星号安全吗?

A:对纯公开接口问题不大,但会带来两个限制:不能携带 cookie 等凭证,且任何网站都能调你的接口。生产环境建议写明确的来源域名,避免被任意第三方站点滥用。

Q:为什么明明加了头还是报跨域?

A:最常见的漏网之鱼是 OPTIONS 预检。当请求带自定义头或非简单方法时,浏览器先发一次 OPTIONS 探路,你得在响应里同时允许对应的方法和头,否则预检不通过,正式请求仍被拦。

Q:代理转发能上生产环境吗?

A:开发服务器(Vite、webpack-dev-server)的代理只跑在本地,不能进生产。生产环境要么后端正确配置 CORS,要么用 Nginx 反向代理把前后端合成同源,思路一致、实现不同。

0 人点赞