本文目录导读:

FastAPI 集成 JWT 非常简单,可以总结为:工具链成熟、代码量少、开箱即用。
主要得益于 python-jose(或 PyJWT)配合 passlib 这两个库,以及 FastAPI 自带的依赖注入系统(Depends),只需几十行代码就能完成完整的注册、登录、Token 下发和接口鉴权。
下面是一个 最简化的完整示例,看完就能理解有多简单:
安装依赖
pip install fastapi uvicorn python-jose[cryptography] passlib[bcrypt] python-multipart
核心代码(完整可运行)
from datetime import datetime, timedelta
from typing import Optional
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import JWTError, jwt
from passlib.context import CryptContext
from pydantic import BaseModel
# ---------- 配置 ----------
SECRET_KEY = "your-secret-key-keep-it-safe" # 生产环境用环境变量
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# ---------- 密码加密 ----------
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
# ---------- 模拟用户数据库 ----------
fake_db = {
"test@example.com": {
"username": "testuser",
"hashed_password": pwd_context.hash("password123")
}
}
# ---------- 数据模型 ----------
class Token(BaseModel):
access_token: str
token_type: str
class UserLogin(BaseModel):
email: str
password: str
class UserInDB(BaseModel):
username: str
email: str
# ---------- 工具函数 ----------
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
def authenticate_user(email: str, password: str):
user = fake_db.get(email)
if not user or not verify_password(password, user["hashed_password"]):
return False
return UserInDB(username=user["username"], email=email)
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
# ---------- FastAPI 依赖:Token 验证 ----------
security = HTTPBearer()
def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
token = credentials.credentials
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
email: str = payload.get("sub")
if email is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = fake_db.get(email)
if user is None:
raise credentials_exception
return UserInDB(username=user["username"], email=email)
# ---------- FastAPI 应用 ----------
app = FastAPI()
@app.post("/login", response_model=Token)
async def login(form_data: UserLogin):
user = authenticate_user(form_data.email, form_data.password)
if not user:
raise HTTPException(status_code=400, detail="Incorrect email or password")
access_token = create_access_token(
data={"sub": user.email},
expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
)
return {"access_token": access_token, "token_type": "bearer"}
# 受保护的接口
@app.get("/users/me", response_model=UserInDB)
async def read_users_me(current_user: UserInDB = Depends(get_current_user)):
return current_user
# 公开接口
@app.get("/")
async def root():
return {"message": "Hello World"}
测试流程
-
启动服务:
uvicorn main:app --reload -
获取 Token(POST /login):
{ "email": "test@example.com", "password": "password123" }返回:
{"access_token": "eyJ...", "token_type": "bearer"} -
访问受保护接口(GET /users/me): 在请求头中加
Authorization: Bearer <你的token>返回用户信息。
为什么简单?
- FastAPI 的依赖注入:
Depends(get_current_user)一行就能保护任意接口,无需写中间件。 - 安全组件现成:
HTTPBearer自动从请求头提取 Bearer Token,你只需处理验证逻辑。 - 密码加密:
passlib对 bcrypt 有开箱即用支持,一行代码完成哈希和验证。 - JWT 库统一:
python-jose的jwt.encode/jwt.decode接口简单直观。
进阶注意(生产环境)
- 密钥管理:用环境变量或密钥管理服务,不要硬编码。
- Token 存储:通常把
sub设为用户 ID,复杂场景可加role等自定义字段。 - Token 刷新:如果需要长连接,实现
/refresh端点并签发短期 access_token + 长期 refresh_token。 - 安全性:HTTPS 传输、黑名单机制(例如登出时把 Token 加入 Redis 黑名单)。
对于常见的 Web 或移动端鉴权场景,FastAPI + JWT 是 Python 生态中最简单的组合之一,尤其适合需要快速搭建 API 服务的团队。