Node.js配置CORS方法及80端口EADDRINUSE错误解决方案
基于Koa框架的Node.js服务示例代码
'use strict'; const app = require('koa')(); const jwt = require('koa-jwt'); const bodyParser = require('koa-bodyparser'); const send = require('koa-send'); const serve = require('koa-static'); const jsonwebtoken = require('jsonwebtoken'); const error = require('./middleware/error-middleware.js'); const router = require('koa-router')(); // 生产环境请勿使用该硬编码密钥 const secret = 'supersecret'; app.use(error()); app.use(bodyParser()); app.use(serve('dist')); app.use(jwt({ secret }).unless({ path: [/^(?!\/api\/)/] })); // 示例逻辑仅做固定账号密码校验 // 生产环境需对接数据库,校验哈希加密后的密码 router.post('/auth', function* () { const username = this.request.body.username; const password = this.request.body.password; if (username !== 'chuck' && password !== 'norris') { this.throw(401, 'Invalid username/password.'); } const user = { username, email: 'chuck@norris.com', firstName: 'Chuck', lastName: 'Norris', roles: ['admin'] }; const token = jsonwebtoken.sign(user, secret, { issuer: 'localhost', audience: 'someaudience', expiresIn: '1d' }); this.body = { token }; }); app.use(router.routes()); app.use(function* () { yield send(this, '/dist/index.html'); }); app.on('error', err => console.log(err)); app.listen(3000, () => console.log('example running on port 3000'));
相关技术问题解答
1. Node.js项目中CORS跨域请求的正确配置方法
Koa项目配置CORS推荐使用官方维护的@koa/cors中间件,配置步骤如下:
- 第一步安装依赖:执行
npm install @koa/cors --save - 第二步注册中间件:必须将cors中间件注册在所有业务路由、jwt校验、bodyParser等其他中间件之前,保证跨域响应头能正常添加到所有响应中。基础配置代码如下:
const cors = require('@koa/cors'); // 放在所有app.use的最前面 app.use(cors());
- 按需自定义配置:如果有允许携带Cookie、限制允许跨域的源、自定义允许的请求头等需求,可以传入配置参数:
app.use(cors({ origin: 'https://你的前端域名.com', // 不要写*,否则携带凭证的请求会失败 credentials: true, // 允许跨域请求携带Cookie、Authorization头 allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowHeaders: ['Content-Type', 'Authorization'] }));
- 额外注意事项:如果项目用了
koa-jwt做鉴权,需要把OPTIONS预检请求加入jwt豁免路径,否则预检请求会因为不带token被拦截,导致跨域失败:
app.use(jwt({ secret }).unless({ path: [/^(?!\/api\/)/], method: 'OPTIONS' // 放行所有OPTIONS预检请求 }));
如果不想引入第三方依赖,也可以手写中间件设置CORS相关响应头,本质就是给每个响应加上Access-Control-Allow-Origin、Access-Control-Allow-Methods等标准跨域头,同时单独处理OPTIONS方法的预检请求即可。
2. 80端口启动报listen EADDRINUSE错误的解决方案与原理
错误原因
EADDRINUSE是系统层面抛出的网络错误,含义是你要监听的本地端口已经被其他进程绑定占用。操作系统规则不允许同一时间同一个网络地址+端口被多个进程同时监听,只要有其他程序已经占了80端口,Node服务再启动绑定这个端口就会直接报错。
除此之外,Linux、macOS系统下1024以下的端口属于系统特权端口,普通用户账号没有直接监听的权限,就算端口没被占用,普通用户启动服务也会报权限错误。
解决方法
- 排查并释放占用80端口的进程:
- Windows系统执行命令
netstat -ano | findstr :80,查到占用端口的进程PID后,执行taskkill /PID 查到的进程号 /F强制结束进程 - macOS/Linux系统执行命令
sudo lsof -i :80查到占用进程的PID,执行sudo kill -9 查到的进程号结束进程
- Windows系统执行命令
- 更安全的生产方案:不要直接用root权限启动Node服务监听80端口,而是让Node服务监听3000这类高位端口,通过Nginx反向代理或者系统端口转发规则,把80端口的入站流量转发到Node服务的端口上,既避免端口冲突,也降低服务运行的安全风险。
- 开发环境直接换用3000、8080这类没有被占用的高位端口启动即可,不需要强行用80端口。
为什么浏览器访问互联网不受该问题影响
浏览器是作为网络客户端发起出站请求,根本不需要在本地监听80端口:
当你用浏览器访问外网网站时,系统会给浏览器分配一个1024以上的随机临时端口作为源端口,去连接远端服务器的80/443目标端口,整个过程本地没有任何进程绑定监听80端口,自然不会和Node服务监听本地80端口的操作产生冲突。
内容的提问来源于stack exchange,提问作者yatender
相关产品推荐
相关产品推荐

