前几天在重构自己产品的时候,打算试试前后端分离的方案。前端使用 Next.js ,后端核心 API 使用 Python,结果在前端调用后端 Python 提供的 API 服务的时候,总是 API 显示 403,然后一步一步排查,从第三方 API 的接口是否能够正常调通?我的网络是否正常?后来才发现是资源共享发生的跨域的问题。因为这个只有在前后端发生分离的时候,才会发生这样的问题。
写下这个笔记,避免以后再发生这样的问题,可以快速找到原因。
什么是 CORS 问题?
CORS(Cross-Origin Resource Sharing, 跨资源共享)是一种浏览器安全机制,用于控制网页是否可以访问不同域名,端口和协议的资源。
什么是”同源”和”跨域”?
浏览器的 同源策略 要求请求必须满足以下三个条件才算”同源”:
- 协议相同 (如都是 http 或 https)
- 域名相同 (如都是 localhost 或 example.com)
- 端口相同 (如都是 3000 或 80)
举例说明
假设你的前端运行在 http://localhost:3000 :
✅ 同源请求 (允许):
❌ 跨域请求 (默认被阻止):
- http://localhost:5000/api/users (端口不同)
- https://localhost:3000/api/users (协议不同)
- http://api.example.com/users (域名不同)
为什么会出现 CORS 问题?
浏览器的同源策略是为了防止恶意网站:
- 窃取用户在其他网站的敏感数据
- 进行 CSRF(跨站请求伪造)攻击
- 未经授权访问用户的私人信息
CORS 的工作原理
简单请求
对于简单的 GET、POST 请求,浏览器会:
- 发送请求到服务器
- 检查响应头中的 Access-Control-Allow-Origin
- 如果包含当前域名或 * ,则允许访问
- 否则阻止并报错
预检请求(Preflight)
对于复杂请求,浏览器会先发送 OPTIONS 请求:
- 发送 OPTIONS 预检请求
- 服务器返回允许的方法、头部等信息
- 如果通过预检,再发送实际请求
解决 CORS 问题的方法
后端配置 CORS(推荐)
1 | from flask import Flask |
前端代理
通过 Next.js 的 rewrite 功能:
1 | const nextConfig = { |
工作原理
- 前端请求 http://localhost:3000/api/crypto/fear-and-greed
- Next.js 服务器代理到 http://localhost:5000/api/crypto/fear-and-greed
- 浏览器认为这是同源请求
- 避免了 CORS 问题
其他解决方案
- 浏览器插件(仅开发时)
- 安装 CORS 插件临时禁用同源策略
- 不推荐 :只能解决开发问题,用户无法使用
启动浏览器时禁用安全检查(仅开发时)
1 | # Chrome(不推荐) |
最佳实践
开发环境
- 使用代理 :Next.js rewrites 或 Vite proxy
- 后端配置宽松的 CORS :允许 localhost 的所有端口
生产环境
- 精确配置 CORS :只允许特定的域名
- 使用 HTTPS :确保安全传输
- 验证 Origin 头 :防止恶意请求
安全建议
1 | # 生产环境的安全配置示例 |
总结
CORS 问题本质上是浏览器的安全保护机制。在你的项目中,通过 Next.js 代理是一个很好的解决方案,因为:
✅ 优点 :
- 完全避免 CORS 问题
- 对前端代码透明
- 可以在代理层添加额外逻辑(如认证、缓存)
✅ 配合后端 CORS 配置 :
- 为直接 API 调用提供支持
- 提供更灵活的部署选项
- 符合 Web 标准
这样既解决了当前问题,又为将来的扩展留下了空间。