前几天在重构自己产品的时候,打算试试前后端分离的方案。前端使用 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

✅ 同源请求 (允许):

❌ 跨域请求 (默认被阻止):

为什么会出现 CORS 问题?

浏览器的同源策略是为了防止恶意网站:

  • 窃取用户在其他网站的敏感数据
  • 进行 CSRF(跨站请求伪造)攻击
  • 未经授权访问用户的私人信息

CORS 的工作原理

简单请求

对于简单的 GET、POST 请求,浏览器会:

  1. 发送请求到服务器
  2. 检查响应头中的 Access-Control-Allow-Origin
  3. 如果包含当前域名或 * ,则允许访问
  4. 否则阻止并报错

预检请求(Preflight)

对于复杂请求,浏览器会先发送 OPTIONS 请求:

  1. 发送 OPTIONS 预检请求
  2. 服务器返回允许的方法、头部等信息
  3. 如果通过预检,再发送实际请求

解决 CORS 问题的方法

后端配置 CORS(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)

# 方法1:允许所有域名(开发环境)
CORS(app)

# 方法2:只允许特定域名(生产环境推荐)
CORS(app, origins=["http://localhost:3000"])

# 方法3:更详细的配置
CORS(app,
origins=["http://localhost:3000"],
methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Content-Type", "Authorization"])

前端代理

通过 Next.js 的 rewrite 功能:

1
2
3
4
5
6
7
8
9
10
const nextConfig = {
async rewrites() {
return [
{
source: "/api/:path*",
destination: "http://localhost:5000/api/:path*",
},
];
},
};

工作原理

其他解决方案

  • 浏览器插件(仅开发时)
    • 安装 CORS 插件临时禁用同源策略
    • 不推荐 :只能解决开发问题,用户无法使用

启动浏览器时禁用安全检查(仅开发时)

1
2
# Chrome(不推荐)
open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security

最佳实践

开发环境

  • 使用代理 :Next.js rewrites 或 Vite proxy
  • 后端配置宽松的 CORS :允许 localhost 的所有端口

生产环境

  • 精确配置 CORS :只允许特定的域名
  • 使用 HTTPS :确保安全传输
  • 验证 Origin 头 :防止恶意请求

安全建议

1
2
3
4
5
6
# 生产环境的安全配置示例
CORS(app,
origins=["https://yourdomain.com"], # 只允许你的域名
methods=["GET", "POST"], # 只允许需要的方法
allow_headers=["Content-Type"], # 只允许必要的头部
supports_credentials=True) # 如果需要发送 cookies

总结

CORS 问题本质上是浏览器的安全保护机制。在你的项目中,通过 Next.js 代理是一个很好的解决方案,因为:

✅ 优点 :

  • 完全避免 CORS 问题
  • 对前端代码透明
  • 可以在代理层添加额外逻辑(如认证、缓存)

✅ 配合后端 CORS 配置 :

  • 为直接 API 调用提供支持
  • 提供更灵活的部署选项
  • 符合 Web 标准

这样既解决了当前问题,又为将来的扩展留下了空间。