现在位置: 首页 > FastAPI 教程 > 正文

FastAPI CORS 跨域

CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种安全机制,允许或限制网页从不同域名请求资源。当前后端分离开发时,前端页面通常运行在不同的域名或端口上,需要配置 CORS 才能正常访问后端 API。


什么是跨域问题

浏览器的同源策略限制了网页向不同域名发送请求。例如:

前端地址后端 API 地址是否跨域
http://localhost:3000http://localhost:8000跨域(端口不同)
http://example.comhttp://api.example.com跨域(域名不同)
https://example.comhttp://example.com跨域(协议不同)
http://example.comhttp://example.com/api同源(相同域名、端口、协议)

同源的三要素:协议域名端口,任一不同即为跨域。


配置 CORS

FastAPI 使用 Starlette 的 CORSMiddleware 来处理跨域:

实例

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 配置 CORS 中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=[               # 允许的源(域名列表)
        "http://localhost:3000",   # 前端开发服务器
        "http://localhost:8080",
    ],
    allow_credentials=True,       # 允许携带 Cookie
    allow_methods=["*"],          # 允许的 HTTP 方法
    allow_headers=["*"],          # 允许的请求头
)

@app.get("/")
async def root():
    return {"message": "Hello World"}

CORS 配置参数详解

参数类型说明推荐值
allow_originslist[str]允许跨域的源列表生产环境用具体域名
allow_methodslist[str]允许的 HTTP 方法["GET", "POST", "PUT", "DELETE"]
allow_headerslist[str]允许的请求头按需配置
allow_credentialsbool是否允许携带 Cookie 和认证信息需要认证时设为 True
expose_headerslist[str]前端可以访问的响应头按需配置
max_ageint预检请求的缓存时间(秒)600

allow_origins 使用 ["*"] 表示允许所有源,但这与 allow_credentials=True 不兼容。如果需要携带 Cookie,必须指定具体的源。


开发环境 vs 生产环境

开发环境

开发时为了方便,可以允许所有源:

实例

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=["*"],         # 允许所有请求头
)

生产环境

生产环境必须指定具体的源:

实例

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 生产环境:只允许特定域名
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "https://example.com",           # 生产前端域名
        "https://www.example.com",       # 带 www 的域名
    ],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
    max_age=600,                  # 预检请求缓存 10 分钟
)

在生产环境中使用 allow_origins=["*"] 是安全隐患,可能导致跨站请求伪造(CSRF)攻击。务必指定具体的前端域名。


CORS 预检请求

浏览器在发送某些跨域请求前,会先发送一个 OPTIONS 预检请求(preflight request),询问服务器是否允许实际请求。CORS 中间件会自动处理预检请求。

需要预检的请求条件:

  • 使用了 PUTDELETE 等非简单方法
  • 请求头包含自定义字段(如 Authorization
  • Content-Type 不是 application/x-www-form-urlencodedmultipart/form-datatext/plain

设置了 max_age 后,浏览器会缓存预检结果,在指定时间内不会重复发送预检请求,减少网络开销。


小结

  • CORS 是浏览器安全机制,前后端分离开发时必须配置
  • 使用 CORSMiddleware 处理跨域请求
  • 生产环境务必指定具体的 allow_origins,不要使用 ["*"]
  • allow_credentials=Trueallow_origins=["*"] 不兼容
  • CORS 中间件自动处理浏览器的 OPTIONS 预检请求