每次新起一个 FastAPI 项目,聊到登录注册、用户角色、Token 刷新这些话题,群里总是一片哀嚎。
明明 FastAPI 官方文档把请求体、依赖注入讲得明明白白,可一到身份验证,瞬间变成大型面向复制粘贴编程现场。
那一刻我就知道,身份验证这事儿,必须得有一套“开箱即用、又不容易犯蠢”的方案。
今天咱们不聊虚的,直接请出我们的主角——FastAPI Users。
我会把它的安装、核心用法、常见坑,以及“到底该不该用”的选择建议,一口气跟你唠明白。
👩💻我是爱折腾的一名程序媛,喜欢研究全栈开发的各种实践,热爱分享踩坑后的收获与思考,也享受用代码写出各种实用小工具解决问题的快乐。
如果你也在技术这条路上向前走,关注我,愿我们能彼此陪伴,一起成为更好的自己🌱
🎯 这篇文章能帮你解决什么
读完你会收获:
🔹 一套完整的 FastAPI 身份验证与用户管理落地方案
🔹 知道什么时候该用 FastAPI Users,什么时候不该用
🔹 避开数据库迁移、依赖冲突等新手高频踩坑点
🔹 直接可跑的代码片段和配置思路
📌 先搞清楚一个问题:为什么不用自己写?
你可能会问:“我照着教程手写 JWT 不香吗?”
香,但“缝缝补补”的成本远比想象的高。
用户注册时的邮箱校验、密码重置、Token 刷新、用户角色控制…… 每增加一个功能,你的auth.py文件就像在打补丁。
更要命的是,安全细节稍有不慎就是致命伤,比如access_token过期时间设得太长、refresh_token没做轮换机制。
FastAPI Users 最让我心动的一点,就是把“最佳实践”封装成了可插拔的模块。
它不绑架你的数据库选择,也不逼你绑定某种前端框架,纯粹在 FastAPI 的依赖注入体系里,帮你搞定了用户管理的 90% 工作。
🧰 核心原理:它到底是怎么运作的?
好,咱们先来拆解一下架构,不用看源码也能懂。
FastAPI Users 本质上是一个依赖注入的集合:
你把用户数据库模型、认证后端(比如 JWT 或 Cookie)、密码哈希策略、邮件发送器等组件分别配置好,然后像乐高一样拼在一起。
它负责生成那些让你头疼的路由:/register、/login、/forgot-password等等。
打个比方,FastAPI 的路由是一个餐厅的出餐口,FastAPI Users 则直接给你预制了一套“顾客点餐、验证会员、找回会员卡”的标准化流程,
你只需要决定会员数据存哪里(SQLite、PostgreSQL 还是 MongoDB),以及会员卡用什么加密方式。
接下来重点来了,它的核心依赖关系:
🔹 用户模型 —— 你用 SQLAlchemy、Tortoise ORM 或 Beanie 定义的用户表
🔹 用户管理器 —— 负责创建、查询、更新用户
🔹 认证后端 —— JWT 策略 或 Cookie 策略,二选一
🔹 可选组件 —— 邮箱验证、角色管理、OAuth 第三方登录等
理解这四层关系,后面的实战配置就轻松了。
🛠️ 实战演示:从零搭一个带用户系统的 FastAPI
这里有一点要特别注意:版本兼容性。
FastAPI Users 的 v10 以上和 v9 差别巨大,千万别对着旧教程盲目复制。咱们以当前稳定的 v12 版本为例。
安装核心库
打开终端,一行搞定:
uv add fastapi-users[sqlalchemy] fastapi uvicorn
这里我用 SQLAlchemy 做演示,因为它社区最广,坑最好找。如果你用 MongoDB,把方括号里换成beanie就行。
定义用户模型
工具的选择上,我认为顺手的才是最好的。既然选了 SQLAlchemy,咱们就用DeclarativeBase加SQLAlchemyUserDatabase的组合。
from fastapi_users.db import SQLAlchemyBaseUserTable, SQLAlchemyUserDatabase
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
pass
class User(SQLAlchemyBaseUserTable[int], Base):
__tablename__ = "user"
# 可以加自定义字段,比如 nickname
nickname: str | None = None
配置用户管理器和认证后端
这里有个很容易翻车的点:一定要用异步引擎,否则和 FastAPI 的协程体系打架,你会看到奇怪的超时错误。
from fastapi_users import FastAPIUsers
from fastapi_users.authentication import JWTStrategy, AuthenticationBackend, BearerTransport
bearer_transport = BearerTransport(tokenUrl="auth/jwt/login")
def get_jwt_strategy() -> JWTStrategy:
return JWTStrategy(secret="YOUR_SUPER_SECRET", lifetime_seconds=3600)
auth_backend = AuthenticationBackend(
name="jwt",
transport=bearer_transport,
get_strategy=get_jwt_strategy,
)
fastapi_users = FastAPIUsers[User, int](
get_async_user_manager,
[auth_backend],
)
这里补充一下get_async_user_manager的定义,它是整个依赖注入链的核心
from fastapi import Depends
from fastapi_users import BaseUserManager, IntegerIDMixin
from sqlalchemy.ext.asyncio import AsyncSession
# 假设你已经有异步数据库会话依赖,通常长这样:
# async def get_async_session() -> AsyncSession:
# async with async_session() as session:
# yield session
class UserManager(IntegerIDMixin, BaseUserManager[User, int]):
"""你可以在这里重写密码校验、注册后处理等钩子"""
# 比如:用户注册后你想自动发邮件,就覆盖 on_after_register 方法
# async def on_after_register(self, user, request=None):
# print(f"用户 {user.email} 注册成功,准备发邮件")
async def get_user_db(session: AsyncSession = Depends(get_async_session)):
yield SQLAlchemyUserDatabase(session, User)
async def get_async_user_manager(user_db: SQLAlchemyUserDatabase = Depends(get_user_db)):
yield UserManager(user_db)