Skip to content

守卫大门: 安全与认证

安全性可能令人望而生畏,但 FastAPI 提供了实现 OAuth2 等标准安全协议的工具,而无需您成为密码学专家。我们将重点关注带密码(和哈希)的 OAuth2 流,它非常适合第一方应用程序(例如由同一组织拥有的前端和后端)。

在此流程中:

  • 用户将用户名和密码发送到 API。
  • API 验证凭据。
  • API 返回一个 token(通常是 JWT - JSON Web Token)。
  • 前端存储此 token,并在后续请求中将其发送到 Authorization 请求头中。

首先,我们使用 OAuth2PasswordBearer 定义 API 期望如何接收 token。tokenUrl 参数告诉前端(以及自动文档)在哪里发送用户名/密码以获取 token。

from fastapi import Depends, FastAPI
from fastapi.security import OAuth2PasswordBearer
from typing import Annotated
app = FastAPI()
# 用户发送凭据的 URL
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

我们安全的核心是一个通常命名为 get_current_user 的依赖项。此依赖项将依赖于我们上面创建的 oauth2_scheme。

当您使用 Depends(oauth2_scheme) 时,FastAPI 将自动查找 Authorization 请求头,提取 Bearer token,并将其作为字符串传递给您的函数。在 get_current_user 内部,您通常会:

  • 解码 JWT token。
  • 检查它是否已过期。
  • 提取用户 ID。
  • 从数据库中获取用户。
  • 如果任何步骤失败,则引发状态码为 401(未授权)的 HTTPException。
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
user = decode_token_and_find_user(token) # 伪代码逻辑
if not user:
raise HTTPException(
status_code=401,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)
return user

现在,保护路由就像将依赖项添加到路径操作函数一样简单。通过添加 Depends(get_current_user),您可以确保函数内部的代码仅在找到有效用户时才运行。

@app.get("/users/me")
async def read_users_me(current_user: Annotated[User, Depends(get_current_user)]):
return current_user

这里的一个巨大好处是自动交互式文档。Swagger UI 现在将显示一个**“Authorize”(授权)**按钮,允许您直接在文档中登录以测试受保护的端点。