FastAPI 与跨域资源共享 CROS

跨域资源共享 CROS

是一种浏览器安全机制,用于允许运行在一个源(Origin)的Web应用通过浏览器向另一个源的服务器发起跨域HTTP请求,并在服务器授权的前提下获取资源。

即 允许服务器"告诉"浏览器,哪些来自不同源(域名/端口/协议)的请求可以被放行。

1. 什么是"同源策略"(Same-Origin Policy)?

这是浏览器的默认安全规则。它规定:如果两个 URL 的协议、域名、端口有一个不同,浏览器就不允许它们互相访问数据。

同源示例:http://localhost:8000/api/usershttp://localhost:8000/docs(同协议、同域名、同端口)。

跨域示例(触犯 CORS):前端页面在 http://localhost:5173,AJAX 请求发往 http://localhost:8000/api/users(端口不同,浏览器会拦截响应)。

2. 为什么要这样设计?

为了防止恶意网站通过脚本窃取你在其他网站(如网银)的登录凭证(Cookie)

真实的报错场景模拟:

前端用 axios 发 POST 请求,数据是 JSON 格式,后端是 FastAPI(没配置 CORS 中间件)。

第一阶段:浏览器(客户端)的"自动安全检查"

前端代码执行:你写了一句 axios.post('http://localhost:8000/users', {name: '张三'})。

浏览器检查请求头:浏览器发现 Content-Type 是 application/json,根据规则,这种请求不能直接发,必须先发一个"探测包"(预检请求),问问服务器同不同意。

探测包发出:浏览器自动生成一个 OPTIONS 请求,发往 http://localhost:8000/users。这个包里的关键信息是:Origin: http://localhost:5173(我是谁)和 Access-Control-Request-Method: POST(我想干什么)。

第二阶段:FastAPI 服务器(没配 CORS)的处理

服务器收到探测包:FastAPI 收到 OPTIONS /users 请求。因为你只写了 @app.post("/users"),没有写 @app.options("/users"),所以 FastAPI 找不到这个路由。

服务器回应探测包:FastAPI 返回一个 404 Not Found 响应。这个响应头里没有 Access-Control-Allow-Origin 字段。

第三阶段:浏览器收到探测响应后的判决

浏览器检查探测响应:浏览器收到了 404 响应,低头一看响应头,发现没有 Access-Control-Allow-Origin。

浏览器直接终止流程:浏览器判定"预检失败",直接把刚才那个 POST /users 请求丢进垃圾桶,压根没往服务器发。

前端报错:浏览器控制台报 CORS error,你的 axios 代码走到了 .catch() 里面。

这个阶段你的业务代码(插入数据库)完全没有执行,因为请求根本没到 FastAPI 的业务层。

第四阶段:如果探测通过了,但正式请求出问题("数据入库但前端报错"的情况)

假设你因为某种原因(比如框架默认支持或者你碰巧配了 OPTIONS)让探测包通过了,浏览器正式发出了 POST 请求。

正式请求到达 FastAPI:请求进入 @app.post("/users"),你的代码执行 db.add(user); await db.commit(); ------ 这时候数据已经成功写入 MySQL 了。

FastAPI 返回正式响应:你的代码最后 return new_user,FastAPI 把状态码 200 和 JSON 数据打包好,发回浏览器。但注意:因为没有全局 CORS 中间件,这个响应头里同样没有 Access-Control-Allow-Origin。

浏览器拦截响应数据:浏览器收到了数据(其实数据已经在网线里跑回来了),但检查响应头时发现没有白名单,它会把这份 JSON 数据拦截在浏览器内核里,坚决不交给前端的 axios 代码。

结果:MySQL 里多了条记录(业务跑了),但前端 axios 的 .then() 永远拿不到返回值,控制台报 CORS 错。

第五阶段:装好 CORSMiddleware 后发生了什么?

中间件拦截探测包:OPTIONS 请求到达后,CORSMiddleware 在路由匹配之前就截获了它,直接返回一个 200 响应,并在响应头里加上 Access-Control-Allow-Origin: http://localhost:5173

浏览器放行正式请求:浏览器拿到允许头,立刻发出真正的 POST 请求。

中间件二次加工响应:POST 请求跑完业务逻辑后,返回的响应在离开服务器前,再次被 CORSMiddleware 拦截,自动在响应头里补上 Access-Control-Allow-Origin。

完美交付:浏览器看到响应头有白名单,不再拦截,把 JSON 数据交给 axios 的 .then() 回调,前端页面成功拿到数据。

CORS 是浏览器施加的安全锁,FastAPI 本身不拦截任何请求(所有请求都照常执行),它只是没有返回让浏览器放行的响应头。你需要通过 CORSMiddleware 主动告诉浏览器:"这个前端源是我信任的,请放行它的响应数据。"

CORS中间件:

from fastapi.middleware.cors import CORSMiddleware

2.定义允许的来源(可以是域名列表)

origins=[

"http://localhost",

"http://localhost:3000",

...等等

]

3.添加 CORS 中间件

fastapi示例名.add_middleware(

CORSMiddleware,

allow_origins="\*", # 允许的源,开发阶段允许所有(*),生产环境需要指定源origins

allow_credentials=True, # 允许携带cookie

allow_methods="\*", # 允许的请求方法

allow_headers="\*", # 允许的请求头

)

相关推荐
troy1282 小时前
Codex 安全盲区:代码漏洞生成实测
windows·python·ci/cd·pycharm·django·github·fastapi
打工仔折腾 AI1 天前
FastAPI 从本机到生产服务器:Nginx+Gunicorn+Uvicorn 完整部署实录
人工智能·后端·python·nginx·fastapi·gunicorn
西安栈上月明软件科技2 天前
从 Linux 0.01 到 AI 开源:星图邻的开源实践
人工智能·自然语言处理·架构·开源·fastapi
troy1282 天前
Python 基础语法(九):Django/Flask/FastAPI 三大 Web 框架详细对比解析
python·jupyter·django·flask·github·fastapi
刚子编程3 天前
Ubuntu 22.04 Docker 从零部署全栈项目实录:Next.js + FastAPI + PostgreSQL 一次跑通
fastapi·nextjs·docker部署·全栈开发·ubuntu22.04
CSharp精选营4 天前
Ubuntu 22.04 Docker 从零部署全栈项目实录:Next.js + FastAPI + PostgreSQL 一次跑通
fastapi·nextjs·docker部署·全栈开发·ubuntu22.04
花酒锄作田5 天前
FastAPI 使用 session 认证
python·fastapi
kyrie_sakura5 天前
python学习笔记14 -- FastAPI
笔记·python·学习·fastapi
the局外人6 天前
学习 FastAPI 的 Day 4:完成用户系统与接口联调(完结)
后端·python·fastapi
李高钢7 天前
Python FastAPI 框架入门:从零搭建你的第一个高性能 API 服务
数据库·python·fastapi