跨域资源共享(CORS,Cross-Origin Resource Sharing)是一个浏览器安全机制,允许网页从不同的域、协议或端口请求资源。在默认情况下,浏览器会阻止网页向与其源不同的域发起请求,这对于安全性至关重要。然而,在开发过程中,通常需要允许跨域请求,尤其是在前后端分离的应用场景下。
FastAPI 提供了简单易用的 CORS 配置,允许你轻松启用和配置跨域请求的处理。
1. 什么是 CORS?
CORS 是一种浏览器机制,它通过设置响应头来告知浏览器某个域是否允许访问另一个域的资源。CORS 主要依赖 HTTP 头部,特别是:
Access-Control-Allow-Origin
:允许访问的来源。Access-Control-Allow-Methods
:允许的 HTTP 方法(如 GET、POST、PUT)。Access-Control-Allow-Headers
:允许请求中包含的 HTTP 头部。Access-Control-Allow-Credentials
:指示是否允许发送 Cookie 信息。
2. FastAPI 中启用和配置 CORS
FastAPI 提供了一个内置的 CORSMiddleware
来帮助我们处理跨域请求。通过这个中间件,我们可以方便地配置哪些来源(Origins)能够访问应用,允许哪些 HTTP 方法,甚至是否允许携带 Cookie。
2.1 安装 CORS 中间件
在 FastAPI 中,CORS 中间件是通过 fastapi.middleware.cors.CORSMiddleware
来实现的。如果你已经安装了 FastAPI 和 Uvicorn,那么 CORS 中间件也是随之安装的。
如果还未安装 FastAPI 和 Uvicorn,可以通过以下命令进行安装:
pip install fastapi uvicorn
2.2 启用 CORS
使用 CORSMiddleware
,我们可以快速启用 CORS,并配置允许的跨域访问来源。以下是一个启用 CORS 的基本示例,允许所有来源访问:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# 配置 CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许所有域名的访问
allow_credentials=True,
allow_methods=["*"], # 允许所有 HTTP 方法(GET、POST 等)
allow_headers=["*"], # 允许所有请求头
)
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
代码解析:
allow_origins=["*"]
:允许来自所有域的跨域请求(*
表示所有域名)。allow_credentials=True
:允许跨域请求时携带用户凭证(如 Cookies)。allow_methods=["*"]
:允许所有 HTTP 方法(如GET
、POST
、PUT
、DELETE
等)。allow_headers=["*"]
:允许所有请求头。
2.3 限制特定来源的跨域请求
在生产环境中,通常不会允许所有来源进行跨域访问,而是需要限制特定的来源。例如,只有来自 https://example.com
和 https://api.example.com
的请求才允许访问 API。
可以通过设置 allow_origins
来指定允许的来源:
app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com", "https://api.example.com"], # 仅允许特定来源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
代码解析:
allow_origins=["https://example.com", "https://api.example.com"]
:只允许https://example.com
和https://api.example.com
域名发起跨域请求。
2.4 配置支持特定 HTTP 方法和头部
你还可以更精细地控制哪些 HTTP 方法和请求头是允许的。例如,限制只允许 GET
和 POST
请求,并且只允许特定的请求头(如 Authorization
):
app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com"],
allow_credentials=True,
allow_methods=["GET", "POST"], # 只允许 GET 和 POST 请求
allow_headers=["Authorization"], # 只允许 Authorization 请求头
)
代码解析:
allow_methods=["GET", "POST"]
:只允许GET
和POST
请求。allow_headers=["Authorization"]
:只允许包含Authorization
请求头的请求。
2.5 允许携带凭证(Cookies)
如果你需要允许跨域请求时携带 Cookie 信息(如用于身份验证的 Cookie),你需要将 allow_credentials
设置为 True
,同时配置 allow_origins
为具体的域名,而不是 *
。
app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com"], # 只允许指定来源
allow_credentials=True, # 允许跨域请求携带 Cookie
allow_methods=["*"],
allow_headers=["*"],
)
代码解析:
allow_credentials=True
:允许跨域请求时发送用户的凭证(如 Cookies)。allow_origins=["https://example.com"]
:allow_credentials=True
时,allow_origins
不能设置为*
,需要指定具体的域名。
3. CORS 中间件工作原理
CORS 中间件在请求处理过程中通过检查 HTTP 请求的头部来决定是否允许跨域请求。它在以下方面发挥作用:
- 请求的预检(Preflight):浏览器在某些情况下会发送一个 OPTIONS 请求(预检请求),用于检查目标服务器是否允许跨域请求。在此请求中,浏览器会发送一些 CORS 相关的头部,如
Access-Control-Request-Method
和Access-Control-Request-Headers
。FastAPI 的 CORS 中间件会拦截并处理这个预检请求,返回允许的请求方法和头部。 - 设置允许的源:CORS 中间件会根据
Access-Control-Allow-Origin
头部,决定是否允许当前请求的来源跨域访问。它会对请求头中的Origin
进行匹配,只有当Origin
符合允许的来源时,才会继续处理请求。 - 跨域请求时携带凭证:如果
allow_credentials=True
,CORS 中间件会允许跨域请求携带凭证,如 Cookies。此时,Access-Control-Allow-Origin
不能是*
,必须指定具体的源。 - 响应修改:CORS 中间件会自动在响应中添加必要的 CORS 头部(如
Access-Control-Allow-Origin
、Access-Control-Allow-Methods
等),以告知浏览器是否允许跨域访问。
4. 处理 CORS 错误
当一个跨域请求违反了 CORS 策略时,浏览器会阻止该请求,并在控制台显示 CORS 错误。最常见的错误是:
- Origin 不匹配:浏览器发送的请求来源与服务器配置的允许的来源不匹配。
- 请求方法不被允许:浏览器发送的请求方法(如
PUT
或DELETE
)没有被服务器允许。 - 请求头不被允许:请求中包含了未被服务器允许的自定义请求头。
要解决这些问题,确保你在服务器端配置了正确的 CORSMiddleware
设置,特别是 allow_origins
、allow_methods
和 allow_headers
。
在 FastAPI 中,启用和配置 CORS 是一个简单的过程,可以通过 CORSMiddleware
中间件来完成。你可以根据需求:
- 允许所有域访问,或者只允许特定来源。
- 配置允许的 HTTP 方法和请求头。
- 控制是否允许跨域请求携带凭证。
通过适当地配置 CORS,你可以确保跨域请求能够在不同的前后端之间顺利进行,而不影响应用的安全性。
更多请关注公众号 “学GIS的小宝同学”