
Koa.js 如何处理 CORS 跨域问题

前言
在现代的 web 开发中,CORS(Cross-Origin Resource Sharing,跨源资源共享)是一个常见的问题。由于浏览器的同源策略限制,当我们尝试进行跨域请求时,例如从 http://domain-a.com
向 http://domain-b.com
发送 AJAX 请求,浏览器会拦截这些请求。幸运的是,Koa 这样的现代框架提供了优雅的解决方案。
在本教程中,我们将通过简单易懂的方式来掌握如何在 Koa 应用中处理 CORS 问题。
浏览器 CORS 工作流程
首先,我们需要理解 CORS 是如何工作的。简单来说,当你的前端应用尝试从不同源(协议 + 域名 + 端口)的服务器请求资源时,浏览器会基于安全考虑发起一个预检请求 (preflight request),询问目标服务器是否愿意接受这个跨源请求。这个预检请求通常使用 OPTIONS
方法。如果服务器响应允许,浏览器才会发送实际的请求。
解决方式
在 Koa 应用中解决 CORS 问题通常有两个步骤:
- 设置响应头: 你需要适当设置 HTTP 响应头,比如
Access-Control-Allow-Origin
,来告诉浏览器你的应用允许来自某个源的请求。 - 处理预检请求: 对于会引发预检的请求类型(如
PUT
、DELETE
或含有自定义头的POST
请求),你需要正确处理OPTIONS
请求。
方式一、CORS 中间件
1. 安装 Koa CORS 中间件
Koa 社区为我们提供了一个非常方便的中间件 @koa/cors
来简化 CORS 设置。首先,你需要安装这个中间件:
shnpm install @koa/cors
2. 使用中间件设置 CORS
安装完成后,你可以在你的 Koa 应用中这样使用它:
javascriptconst Koa = require('koa'); const cors = require('@koa/cors'); const app = new Koa(); // 使用默认配置启用 CORS app.use(cors()); // 或者自定义配置 // 例如,只允许来自 http://example.com 的跨源请求 app.use(cors({ origin: 'http://example.com' })); // 其他中间件和路由 // ... app.listen(3000);
方式二、自定义 CORS 响应头
如果你需要进一步自定义 CORS 行为,比如设置 Access-Control-Allow-Methods
或 Access-Control-Allow-Headers
,你可以在 cors()
方法中传入更多选项:
javascriptapp.use(cors({ origin: '*', allowMethods: ['GET', 'POST', 'DELETE'], allowHeaders: ['Content-Type', 'Authorization'], }));
方式三、动态设置 CORS
在实际应用中,你可能需要根据不同的请求动态设置 CORS。@koa/cors
中间件也支持这样的操作,你可以传入一个函数来动态决定 origin
:
javascriptapp.use(cors({ origin: (ctx) => { if (ctx.url === '/test') { // 只有 /test 路径支持来自特定源的跨域请求 return 'http://allowed-origin.com'; } return 'http://default-origin.com'; } }));
方式四、手动设置 CORS
在没有使用 @koa/cors
的情况下,你可以通过设置 Koa 上下文(ctx
)的响应头部来实现 CORS。这里是一个简单的例子:
javascriptapp.use(async (ctx, next) => { const allowedOrigins = ['http://allowed-origin.com', 'http://another-allowed-origin.com']; const origin = ctx.request.headers.origin; if (allowedOrigins.includes(origin)) { ctx.set('Access-Control-Allow-Origin', origin); } // 设置允许的方法 ctx.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); // 如果你希望接收 cookies 或者允许一些特定的头部,则需要设置以下两个 Header ctx.set('Access-Control-Allow-Credentials', 'true'); ctx.set('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 对于预检请求,我们只需要返回状态码 204 即可 if (ctx.method === 'OPTIONS') { ctx.status = 204; } else { await next(); } });
这个自定义中间件检查了请求头部中的 Origin
,并且只有在白名单中的源才被允许。它还为可能的预检请求设置了正确的处理方法。
注意事项
- 在设置 CORS 策略时,尽量避免使用
origin: '*'
(允许所有源),除非你完全确定你的资源可以公开。 - 如果你需要处理带有敏感数据的请求,确保你配置了
Access-Control-Allow-Credentials
,并且不要设置origin
为'*'
,因为这样会导致浏览器忽略Access-Control-Allow-Credentials
。 - 在生产环境下,避免将 CORS 配置硬编码到代码中。最好是使用环境变量或配置文件来管理你的 CORS 白名单。
总结
通过本教程,你应该已经掌握了在 Koa 应用中处理 CORS 问题的基本方法和一些最佳实践。使用 @koa/cors
中间件,你可以非常轻松地对 CORS 进行配置,从而使得你的前端应用能够安全地与后端服务通信。
你还可以根据需要调整 CORS 策略,以找到安全与可用性的最,好的平衡点。另外,不要忘了定期回顾和测试你的 CORS 策略,确保它既符合业务需求,又不会无意中暴露敏感数据。
如果你的应用不允许使用第三方中间件,或者你想要深入了解 Koa 如何手动处理 CORS,你也可以通过编写自定义的中间件来实现。