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="\*", # 允许的请求头

)

相关推荐
Gain_chance3 小时前
大数据毕业设计实战|Data Insight Platform:用 FastAPI + ClickHouse 打造低门槛全链路数据洞察平台
大数据·数据库·clickhouse·毕业设计·fastapi
逆风飞翔的小叔19 小时前
【Python基础】FastAPI 从入门到项目实战操作详解
fastapi·fastapi 详解·fastapi 使用详解·fastapi 请求参数详解·fastapi 总结
卷无止境2 天前
当FastAPI遇上机器学习,一个脚手架工具能省下多少工夫
后端·python·fastapi
练习两年半的攻城狮2 天前
【RAG实战】知识库 BGE-M3 稀疏向量混合检索方案
python·fastapi·llamaindex
哒咩哒咩1292 天前
Agent 智能体开发全攻略:从 ReAct 到企业级架构
python·langchain·fastapi
创新技术阁3 天前
FastapiAdmin 前后端启动全流程详解
前端·后端·fastapi
典典分享指南3 天前
飞书 + 企业微信 + 微信文档多端协同实践指南
汇编·flask·intellij-idea·fastapi
鲨鱼辣钊3 天前
FastAPI筑基_Day15_Alembic数据库迁移实战
数据库·elasticsearch·fastapi
Broccoli523026653 天前
FastAPI 中 Pydantic 模型与 SQLAlchemy ORM 模型的分工与转换规范
fastapi