FastAPI CORS 跨域配置详解
文章目录
前后端分离开发时,浏览器控制台突然冒出一行红字:”Access to fetch at ‘http://localhost:8000/api‘ from origin ‘http://localhost:3000‘ has been blocked by CORS policy”。这是几乎所有 Web 开发者都会遇到的经典跨域报错。FastAPI 通过内置的 CORSMiddleware 优雅地解决了这个问题,但理解其背后的机制才能避免”一把梭允许所有来源”的安全隐患。
什么是 CORS
CORS(Cross-Origin Resource Sharing,跨域资源共享)是浏览器的一种安全策略。当网页发起 HTTP 请求时,如果请求的目标地址与当前页面的协议、域名、端口任意一项不同,就属于跨域请求,浏览器会先检查服务器是否明确允许。
判断是否同源的三要素:
| 当前页面 | 请求目标 | 是否跨域 |
|---|---|---|
http://a.com |
http://a.com/api |
❌ 同源 |
http://a.com |
https://a.com |
✅ 协议不同 |
http://a.com |
http://b.com |
✅ 域名不同 |
http://a.com:3000 |
http://a.com:8000 |
✅ 端口不同 |
本地开发中,前端(如 Vite 的 localhost:5173)和后端(如 FastAPI 的 localhost:8000)端口不同,自然触发跨域检查。
FastAPI 中的 CORS 配置
FastAPI 通过 CORSMiddleware 中间件来处理跨域,核心配置只有几行:
1 | from fastapi import FastAPI |
关键参数说明
**allow_origins**:最重要的参数,指定哪些前端域名可以访问你的 API。必须精确匹配,http://localhost 和 https://localhost 被视为不同的源。开发阶段常用 ["*"] 允许所有来源,但生产环境必须限制为具体的域名列表。
**allow_credentials:是否允许请求携带 Cookie 和 HTTP 认证信息。当设为 True 时,allow_origins 不能为 ["*"]**,必须指定具体域名,这是浏览器的强制安全限制。
**allow_methods**:允许的 HTTP 方法。默认只允许 GET,如果你的 API 涉及 POST、PUT、DELETE 等操作,必须显式声明。
**allow_headers**:允许客户端发送的请求头。前后端分离中常见的 Authorization、Content-Type 等需要在此声明。
允许所有来源(仅限开发/公开 API)
1 | app.add_middleware( |
允许所有来源时 allow_credentials 必须是 False,否则浏览器会拒绝请求。对于无需身份认证的公开 API,这个配置是合理的。
预检请求(Preflight Request)
当请求不是”简单请求”时,浏览器会先自动发送一个 OPTIONS 请求来”探路”,询问服务器是否允许即将发起的请求。这个过程叫预检请求。
以下情况会触发预检:
- 使用
PUT、DELETE、PATCH等方法 Content-Type不是application/x-www-form-urlencoded、multipart/form-data、text/plain- 使用了自定义请求头(如
Authorization、X-Requested-With)
1 | # 这个请求会触发预检:PUT 方法 + JSON + Authorization 头 |
CORSMiddleware 自动处理 OPTIONS 请求并返回正确的响应头,开发者无需手动编写 OPTIONS 路由。
实际案例:前后端分离项目配置
假设项目结构如下——前端 React 跑在 localhost:3000,后端 FastAPI 跑在 localhost:8000,需要携带 Cookie 做身份认证:
1 | from fastapi import FastAPI |
expose_headers 参数值得一提:默认情况下,浏览器只允许 JavaScript 读取响应的 Cache-Control、Content-Type 等 7 个简单头。如果你的后端在返回自定义头(如分页的 X-Total-Count),必须通过 expose_headers 暴露给前端。
常见问题排查
1. 配置了 CORS 但仍报跨域错误
首先检查 allow_origins 是否包含了完整的 origin(含协议和端口)。用浏览器开发者工具的 Network 面板查看响应头中是否有 Access-Control-Allow-Origin,如果返回了但值不对,通常就是 origin 拼写问题。
2. Cookie 无法传递
确认 allow_credentials=True 且前端请求也开启了 credentials: 'include':
1 | fetch("/api/me", { credentials: "include" }) |
同时检查 allow_origins 是具体域名而非 ["*"]。
3. 预检请求返回 405
检查 allow_methods 是否包含目标 HTTP 方法,以及 allow_headers 是否包含自定义请求头。
总结
FastAPI 的 CORS 配置本质上是对浏览器安全策略的声明——告诉浏览器哪些来源可以访问资源。核心记住三点:allow_origins 精确匹配来源、allow_credentials 为 True 时必须用具体域名、非简单请求会自动触发 OPTIONS 预检。开发阶段可以用宽松配置快速验证,但上线前务必收紧为具体的域名列表。