Egg.js跨域问题完美解决方案:CORS配置详解
在前后端分离架构中,跨域资源共享(CORS,Cross-Origin Resource Sharing)是开发者绕不开的挑战。当前端应用与后端API部署在不同域名下时,浏览器的同源策略会阻止跨域请求,导致接口调用失败。作为基于Node.js和Koa的企业级框架,Egg.js提供了灵活且安全的跨域解决方案。本文将从问题分析到实际配置,带你彻底解决Egg.js应用中的跨域难题。
跨域问题原理与表现
跨域问题本质是浏览器的安全机制限制。当满足以下任一条件时,请求会被判定为跨域:
- 协议不同(如HTTP与HTTPS)
- 域名不同(如example.com与api.example.com)
- 端口不同(如80端口与3000端口)
典型错误表现为控制台出现类似提示:
Access to XMLHttpRequest at 'https://api.example.com/data' from origin 'https://example.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Egg.js中间件解决方案
Egg.js采用中间件机制处理HTTP请求流程,跨域问题可通过配置CORS中间件解决。框架兼容所有Koa生态的CORS中间件,推荐使用成熟的koa-cors模块。
安装依赖
npm install koa-cors --save
创建CORS中间件
在项目中创建中间件文件:
// app/middleware/cors.js
module.exports = require('koa-cors');
全局启用配置
修改配置文件启用CORS中间件:
// config/config.default.js
module.exports = {
// 加载cors中间件
middleware: [ 'cors' ],
// cors中间件配置
cors: {
origin: '*', // 允许所有域名访问,生产环境建议指定具体域名
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH', // 允许的HTTP方法
allowHeaders: 'Content-Type,Authorization', // 允许的请求头
exposeHeaders: 'Content-Length,Date,ETag', // 允许客户端获取的响应头
maxAge: 86400, // 预检请求缓存时间(秒)
credentials: true, // 是否允许发送Cookie
},
};
精细化跨域控制
实际项目中,完全开放的跨域策略可能带来安全风险。Egg.js中间件支持通过match和ignore配置实现精细化控制。
路径匹配规则
// config/config.default.js
module.exports = {
cors: {
// 仅对/api路径启用跨域
match: '/api',
// 或者使用正则表达式匹配
// match: /^\/api\//,
// 或者使用函数自定义匹配逻辑
// match(ctx) {
// return ctx.path.startsWith('/api');
// },
origin: 'https://example.com',
credentials: true,
},
};
多环境配置
不同环境可能需要不同的跨域策略,可通过环境配置文件区分:
// config/config.local.js (开发环境)
module.exports = {
cors: {
origin: '*', // 开发环境宽松策略
},
};
// config/config.prod.js (生产环境)
module.exports = {
cors: {
origin: 'https://example.com', // 生产环境严格指定域名
},
};
安全策略与CORS的协同
Egg.js内置的安全插件提供了多种防护机制,配置CORS时需注意与这些安全策略的协同工作。
CSRF防护兼容
当启用CORS并允许 credentials 时,需特别注意CSRF防护:
// config/config.default.js
module.exports = {
security: {
csrf: {
// 对跨域请求忽略CSRF检查
ignore: ctx => ctx.get('origin'),
},
},
};
安全域名白名单
对于需要重定向的场景,可配置安全域名白名单:
// config/config.default.js
module.exports = {
security: {
domainWhiteList: [ 'https://example.com' ], // 跨域重定向白名单
},
};
常见问题解决方案
预检请求失败
若遇到OPTIONS预检请求失败,检查是否正确配置了允许的请求头和方法:
// 正确配置示例
cors: {
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
allowHeaders: 'Content-Type,Authorization,X-Requested-With',
}
带Cookie的跨域请求
当需要在跨域请求中传递Cookie,需确保三方面配置:
- 服务端设置
credentials: true - 客户端请求时设置
withCredentials: true origin不能设置为*,必须指定具体域名
复杂请求处理
对于包含自定义头或非简单方法的复杂请求,浏览器会先发送预检请求。可通过配置maxAge减少预检请求次数:
cors: {
maxAge: 86400, // 预检结果缓存24小时
}
最佳实践与注意事项
生产环境配置建议
// 生产环境安全配置
cors: {
origin: ctx => {
const allowedOrigins = [ 'https://example.com', 'https://admin.example.com' ];
const origin = ctx.get('origin');
return allowedOrigins.includes(origin) ? origin : '';
},
credentials: true,
allowMethods: 'GET,POST,PUT,DELETE',
maxAge: 86400,
}
中间件顺序问题
确保CORS中间件在路由处理之前执行:
// config/config.default.js
module.exports = {
// 中间件加载顺序,cors应放在前面
middleware: [ 'cors', 'otherMiddleware' ],
};
调试技巧
遇到跨域问题时,可通过以下方式排查:
- 查看浏览器控制台的网络请求,检查预检请求和实际请求的响应头
- 使用Egg.js的日志功能输出CORS配置:
// app.js
module.exports = app => {
console.log('CORS配置:', app.config.cors);
};
通过本文介绍的方法,你可以在Egg.js应用中实现安全、灵活的跨域资源共享配置。合理的CORS策略不仅能解决前后端分离架构中的通信问题,还能在安全性和开发效率之间取得平衡。实际项目中,建议根据具体的业务场景和安全要求,选择最适合的跨域解决方案。
更多关于Egg.js中间件的使用细节,可参考官方文档:docs/source/zh-cn/basics/middleware.md
安全相关配置可参考:docs/source/zh-cn/core/security.md
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



