FastAPI 的 CORSMiddleware 跨域中间件

一、什么是跨域?为什么会被拦截?

1. 浏览器的安全规则:同源策略

浏览器默认禁止 :一个域名下的前端网页,去请求另一个不同域名 / 端口 / 协议的后端接口。

只要下面 3 个有一个不一样,就是跨域

  1. 协议(http /https)
  2. 域名(localhost / 127.0.0.1 / www.xxx.com
  3. 端口(3000 / 8000 / 8080)

2. 最常见的场景

  • 前端:localhost:3000(React/Vue/ 小程序)
  • 后端:localhost:8000(FastAPI)

端口不同 → 跨域 → 浏览器直接拦截请求你会在控制台看到经典报错:

plaintext

rust 复制代码
Access to XMLHttpRequest at 'http://localhost:8000/xxx'
from origin 'http://localhost:3000' has been blocked by CORS policy.

二、CORSMiddleware 到底做了什么?

一句话:给后端接口添加允许跨域的响应头,告诉浏览器:这个请求是安全的,放行!

核心就是在 HTTP 响应里加一行:

plaintext

makefile 复制代码
Access-Control-Allow-Origin: *

浏览器看到这行,就不再拦截。


三、逐行代码详细解析

完整代码

python

运行

ini 复制代码
# 导入 FastAPI 的跨域中间件
from fastapi.middleware.cors import CORSMiddleware

# 创建 FastAPI 实例
app = FastAPI()

# 配置允许跨域
app.add_middleware(
    CORSMiddleware,        # 使用的中间件
    allow_origins=["*"],   # 允许哪些来源(域名/前端地址)
    allow_credentials=True,  # 允许携带Cookie
    allow_methods=["*"],     # 允许所有请求方法(GET/POST/PUT/DELETE)
    allow_headers=["*"],     # 允许所有请求头
)

逐参数解释

  1. allow_origins=["*"]

    • * = 允许所有来源跨域
    • 生产环境可以写死:["https://your-frontend.com"]
  2. allow_credentials=True

    • 允许前端带 cookie、token 跨域请求
  3. allow_methods=["*"]

    • 允许所有 HTTP 方法:GET、POST、PUT、DELETE 等
  4. allow_headers=["*"]

    • 允许所有请求头,比如 AuthorizationContent-Type

四、极简工作流程

  1. 前端(localhost:3000)→ 请求后端(localhost:8000
  2. 浏览器发现跨域,先检查后端响应头
  3. 后端加了 CORSMiddleware → 响应头带上 允许跨域
  4. 浏览器看到允许 → 正常请求成功

五、为什么必须后端配置,前端不能解决?

跨域是浏览器的安全限制 ,不是后端限制,也不是前端限制。只有后端明确授权,浏览器才会放行。


六、最实用的两种配置

1. 开发环境(允许所有)

python

运行

ini 复制代码
allow_origins=["*"]

2. 生产环境(只允许你的前端域名)

python

运行

ini 复制代码
allow_origins=[
    "https://www.your-app.com",
    "https://app.your-app.com"
]

七、一句话总结

CORSMiddleware 就是给后端开 "跨域通行证" ,让前端(3000 端口)可以正常调用后端(8000 端口),解决浏览器的跨域拦截报错。


你只要记住

  • 前后端端口不同 = 跨域
  • 跨域会被浏览器拦截
  • 加这段代码 = 后端允许跨域
  • 浏览器看到允许 = 请求成功

需要我给你演示一个完整可运行的 FastAPI + 跨域 + 接口的最小 demo 吗?复制就能跑。

再详细一点

超深度详解 FastAPI CORSMiddleware

浏览器同源策略底层跨域触发条件预检请求中间件源码逻辑每个参数底层含义生产踩坑,全给你掰开讲透。


一、先底层:浏览器 同源策略 Same-Origin Policy

1. 什么是「源 Origin」

一个源由三部分组成:协议 + 域名 + 端口

  • 协议:http / https
  • 域名:localhost / 127.0.0.1 / baidu.com
  • 端口:8000 / 3000 / 8080

三个完全一致 = 同源****任意一个不同 = 跨域

2. 同源策略的目的

浏览器安全机制:防止恶意网站偷偷读取你登录态、Cookie、本地存储、接口数据。比如你登录了银行网站,恶意网页不能随便调银行接口偷数据。

3. 哪些行为受跨域限制

  • Ajax / Fetch / Axios 请求后端接口
  • 读取跨域 Cookie、LocalStorage
  • 跨域 DOM 访问

普通 <img src=""><script src=""><link> 不受跨域限制,这是浏览器设计特例。


二、什么是 CORS?

CORS = Cross-Origin Resource Sharing 跨域资源共享W3C 标准 ,用来合法绕过同源策略

原理:**后端通过 HTTP 响应头,主动告诉浏览器:我允许某个前端源跨域访问我。**浏览器拿到合法响应头,就放行请求;没有就直接拦截,控制台报错。


三、为什么会出现跨域(经典场景)

前端:http://localhost:3000后端:http://localhost:8000

协议相同、域名相同、端口不同 → 跨域浏览器直接拦截前端的 Fetch/Axios 请求。

注意:跨域只限制浏览器 ,Postman、后端调后端、curl 命令完全不受跨域限制 。跨域不是后端不让你访问,是浏览器拦的


四、浏览器两种跨域请求类型

1. 简单请求

满足全部条件:

  • 请求方法:GET / POST / HEAD
  • 请求头只有:AcceptAccept-LanguageContent-LanguageContent-Type(仅三种值)
  • 没有自定义请求头(比如不带 Authorization: Bearer token

流程:直接发真实请求,后端返回跨域响应头,浏览器判断是否放行。

2. 预检请求 Preflight(OPTIONS)

只要不满足简单请求,浏览器会先发一次 OPTIONS 预检请求 :问后端:我这个跨域请求允许吗?允许什么方法、什么头、带不带凭证?后端返回允许的头,浏览器才会发真实 POST/PUT/DELETE 请求

常见触发预检:

  • 带自定义请求头 Authorization
  • Content-Type: application/json
  • PUT / DELETE / PATCH 方法

👉 FastAPI 的 CORSMiddleware 自动帮你处理 OPTIONS 预检请求,不用自己写接口处理 OPTIONS。


五、代码本体解析

python

运行

javascript 复制代码
from fastapi.middleware.cors import CORSMiddleware
  • 来自 starlette 底层的跨域中间件(FastAPI 基于 Starlette)
  • 作用:拦截所有进入后端的 HTTP 请求
  • 自动识别跨域 Origin
  • 自动在响应头插入 CORS 相关字段
  • 自动响应 OPTIONS 预检请求

完整配置模板:

python

运行

ini 复制代码
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
    max_age=3600
)

六、逐个参数 底层深度解释

1. allow_origins

作用:允许哪些前端源访问后端

  • ["*"]:允许所有任意域名跨域
  • 指定域名:["http://localhost:3000", "https://xxx.com"]

底层响应头:

plaintext

makefile 复制代码
Access-Control-Allow-Origin: 对应域名

重点坑点 :如果 allow_credentials=True,**不能用 allow_origins=["*"]**浏览器规则:允许携带凭证时,禁止使用通配符 *,必须写死具体域名。

2. allow_credentials=True

作用:允许跨域请求携带

  • Cookie
  • HttpOnly Cookie
  • 认证头部、会话凭证

底层响应头:

plaintext

yaml 复制代码
Access-Control-Allow-Credentials: true

登录态、Token 放 Cookie 里跨域,必须开这个。

3. allow_methods=["*"]

允许跨域使用哪些 HTTP 请求方法GET POST PUT DELETE PATCH OPTIONS

底层响应头:

plaintext

makefile 复制代码
Access-Control-Allow-Methods: GET,POST,PUT,DELETE...

4. allow_headers=["*"]

允许前端带哪些自定义请求头 比如:AuthorizationX-TokenContent-Type

底层响应头:

plaintext

makefile 复制代码
Access-Control-Allow-Headers: Authorization,Content-Type...

前端传 Token 鉴权,必须配置这个。

5. max_age=3600

预检请求缓存时间(单位秒)浏览器 1 小时内不用再发 OPTIONS 预检,直接请求,提升性能。


七、中间件底层工作流程

  1. 前端发起跨域请求

  2. 请求先经过 FastAPI 中间件层 CORSMiddleware

  3. 中间件提取请求头 Origin

  4. 校验这个 Origin 是否在 allow_origins 允许列表

  5. 如果允许:

    • 在响应头自动塞入所有 CORS 字段
    • 若是 OPTIONS 预检请求,直接返回 200 空响应,不进入业务接口
  6. 浏览器拿到响应头,校验通过 → 放行请求


八、开发环境 vs 生产环境 标准写法

开发环境(省事)

python

运行

ini 复制代码
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

缺点 :不能同时开 allow_credentials=True

生产环境(规范安全)

python

运行

ini 复制代码
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:3000",
        "https://your-frontend.com"
    ],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
    max_age=3600
)
  • 不使用 *
  • 精确放行前端域名
  • 限定请求方法、请求头
  • 开启凭证,支持 Cookie/Token 登录

九、核心总结一句话

  1. 跨域是浏览器同源策略限制,不是后端限制;
  2. CORSMiddleware后端主动给响应头授权,告诉浏览器允许跨域;
  3. 自动处理 OPTIONS 预检请求,不用手写接口;
  4. 开发可用 *,生产必须指定具体域名 ,开凭证就不能用 *
  5. Authorization、JSON 请求、增删改接口,都会触发预检,靠这个中间件自动处理。

CORS 跨域完整时序流程图 + 文字逐帧拆解

一、先分清两种请求:简单请求 / 预检请求

1. 简单请求 时序图

plaintext

bash 复制代码
前端浏览器(localhost:3000)
        ↓ 发起 GET/普通POST
        ↓ 无自定义头、无application/json
浏览器拦截校验:发现跨域
        ↓
向后端直接发起真实请求
        ↓
FastAPI + CORSMiddleware
        ↓
中间件自动添加CORS响应头:
Access-Control-Allow-Origin
        ↓
返回响应给浏览器
        ↓
浏览器校验响应头合法 → 放行 → 前端拿到数据

文字流程拆解

  1. 前端 fetch/axios简单 GET / 普通 POST
  2. 浏览器识别:协议 / 域名 / 端口不一致 → 跨域
  3. 直接发真实请求,不先发 OPTIONS
  4. 请求到达 FastAPI,先走 CORSMiddleware 中间件
  5. 中间件匹配 Origin,自动塞入跨域响应头
  6. 浏览器拿到响应头,核对允许规则
  7. 校验通过,把数据交给前端业务代码

2. 预检请求 (OPTIONS) 标准时序(90% 项目都是这种)

触发场景:

  • Authorization 令牌头
  • Content-Type: application/json
  • PUT / DELETE / PATCH 方法

plaintext

scss 复制代码
前端浏览器(localhost:3000)
        ↓
浏览器先拦截:这不满足简单请求 → 必须预检
        ↓ 自动先发 OPTIONS 预检请求
FastAPI CORSMiddleware 拦截
        ↓
中间件校验 Origin、方法、请求头是否在白名单
        ↓
返回 200 + 一串CORS预检响应头
(Allow-Origin / Allow-Methods / Allow-Headers / Max-Age)
        ↓
浏览器收到预检结果:合法
        ↓ 间隔极短,立刻发起【真实业务请求】(POST/PUT/DELETE)
后端正常执行业务接口逻辑
        ↓
返回业务数据 + 跨域响应头
        ↓
浏览器放行,前端拿到真实结果

逐步拆解

  1. 前端要发 JSON 格式、带 Token、非 GET 请求
  2. 浏览器不会直接发业务请求 ,先自作主张发一次 OPTIONS 预检
  3. 请求到达 FastAPI,CORSMiddleware 接管 OPTIONS 请求
  4. 中间件不进你的业务接口,直接返回 200 和预检头
  5. 浏览器确认:域名、方法、请求头都被允许
  6. 再发起真正的业务 POST/PUT 请求
  7. 后端正常处理接口,返回数据
  8. 浏览器再次校验响应头,放行给前端

二、CORSMiddleware 在 FastAPI 整体链路位置

plaintext

markdown 复制代码
客户端请求
    ↓
FastAPI 中间件层
  ↳ CORSMiddleware(最先拦截)
    ↓
路由匹配
    ↓
接口函数执行业务逻辑
    ↓
响应原路返回
    ↓
中间件加上CORS响应头
    ↓
浏览器

核心关键点:

  • 跨域校验在中间件层就做完了
  • OPTIONS 预检请求根本不会进到你写的接口代码,中间件直接拦截并返回

三、必记致命坑(对应你配置参数)

  1. allow_credentials=True绝对不能allow_origins=["*"]浏览器强制规则:允许 Cookie / 凭证 就禁止通配符,必须写死具体域名。
  2. 前端带 Authorization: Bearer xxx必然触发 OPTIONS 预检,必须靠中间件自动处理,自己手写接口很难兼容。
  3. max_age=3600预检结果缓存 1 小时,这段时间内同类型请求不再发 OPTIONS,提升性能。

四、极简口诀背下来

  • 三要素不同就是跨域:协议、域名、端口

  • 跨域是浏览器拦的,不是后端不让访问

  • 普通 GET 走简单请求 ,带 Token/JSON 走预检 OPTIONS

  • CORSMiddleware 做三件事:

    1. 识别跨域 Origin
    2. 自动响应 OPTIONS 预检
    3. 给响应头加跨域授权字段
  • 开发可用*,生产写死域名 ,开凭证不能用*

FastAPI CORS 生产 + 开发 两套标准模板(直接复制即用)

一、开发环境模板(本地调试用)

特点:随便跨域、省事、不用写前端域名

python

运行

ini 复制代码
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 开发环境 CORS 配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],        # 允许所有前端源
    allow_methods=["*"],        # 允许所有请求方法
    allow_headers=["*"],        # 允许所有请求头
    max_age=3600                # 预检缓存1小时
)

⚠️ 注意:这套不能加 allow_credentials=True ,一加就报错,浏览器不允许 * + 带凭证。


二、生产环境标准模板(企业级规范,推荐一直用)

特点:安全、精准放行、支持 Cookie/Token/ 登录凭证、兼容预检请求

python

运行

ini 复制代码
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 生产环境 允许的前端域名白名单
ALLOW_ORIGINS = [
    "http://localhost:3000",
    "http://localhost:5173",
    "https://your-frontend.com",
    "https://admin.your-frontend.com"
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=ALLOW_ORIGINS,
    allow_credentials=True,       # 允许跨域带 Cookie、Token、会话凭证
    allow_methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
    allow_headers=["Authorization", "Content-Type", "X-Token"],
    max_age=3600
)

三、关键参数固定解释(以后不用再查)

  1. allow_origins只填你真实前端地址 ,不写 *,防止恶意网站盗用接口。
  2. allow_credentials=True必须开:
  • 前端带 Authorization 令牌
  • 登录存 Cookie、会话保持开了就不能用 ["*"]
  1. allow_methods只开放业务用到的请求方法,最小权限安全原则。
  2. allow_headers只放行认证头、内容类型头,不要无脑全开放。
  3. max_age=3600缓存 OPTIONS 预检结果,1 小时内不再重复发预检,提升接口速度。

四、最佳实践写法(适配开发 / 生产自动切换)

python

运行

ini 复制代码
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import os

app = FastAPI()

# 环境变量区分开发/生产
ENV = os.getenv("ENV", "dev")

if ENV == "dev":
    # 开发
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_methods=["*"],
        allow_headers=["*"],
        max_age=3600
    )
else:
    # 生产
    ALLOW_ORIGINS = [
        "https://your-frontend.com",
        "https://admin.your-frontend.com"
    ]
    app.add_middleware(
        CORSMiddleware,
        allow_origins=ALLOW_ORIGINS,
        allow_credentials=True,
        allow_methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
        allow_headers=["Authorization", "Content-Type"],
        max_age=3600
    )

以后新建 FastAPI 项目,直接复制这段,不用再手写 CORS。

相关推荐
shchojj1 小时前
What is Generative AI - How generative AI works
人工智能
xingyuzhisuan1 小时前
哪里可以一键部署Stable Diffusion XL的GPU云环境?(2026实测指南)
运维·人工智能·stable diffusion·gpu算力
shchojj2 小时前
What is Generative AI - AI is a general purpose technology
人工智能
Agent手记2 小时前
采购合同智能审核自动化,落地步骤与落地风险管控方案 —— 2026年企业级Agent深度实战指南
运维·人工智能·ai·自动化
byte轻骑兵2 小时前
【LE Audio】CAP精讲[5]: 导演上线!Initiator音频协同全流程合规指南
人工智能·音视频·低功耗·le audio
3D探路人2 小时前
模灵 大模型聚合API 转发流程技术实现
java·大数据·开发语言·前端·人工智能·计算机视觉
Ares-Wang2 小时前
图像》》仿射变换和透视变换放 、图像分割、目标检测
人工智能·计算机视觉
艾醒(AiXing-w)2 小时前
从Prompt到Harness:AI Agent三代工程化全解析
人工智能
空中湖2 小时前
AI 指数级进化 · 一场跨越千年的智能之旅
人工智能