新闻中心
FastAPI实现多重可选认证:同时支持Basic Auth与JWT Auth

本文详细阐述如何在FastAPI中实现灵活的多重认证机制,允许客户端通过Basic Auth或JWT Bearer Token中的任意一种方式访问受保护的API端点。核心策略是将各个认证依赖项配置为在认证失败时不立即抛出异常,而是返回None,从而将最终的授权决策和错误处理集中到一个高级组合依赖中。
在构建现代Web API时,常常需要支持多种认证方式以适应不同的客户端或使用场景。例如,某些内部服务可能使用Basic Auth,而外部客户端则可能依赖JWT。FastAPI的依赖注入系统非常强大,但默认情况下,当一个端点声明了多个认证依赖时,FastAPI会尝试强制所有依赖都成功。这导致了一个常见问题:如何让端点支持“或”逻辑,即只要任意一种认证方式成功即可访问?
本文将通过一个具体的示例,演示如何改造FastAPI的认证依赖,使其能够灵活地支持Basic Auth或JWT Auth的任选模式。
1. 核心理念:非阻塞式认证依赖
解决此问题的关键在于,让单个的认证依赖项在认证失败时不再立即抛出HTTPException,而是返回一个指示失败的值(通常是None)。这样,上层组合依赖就可以根据这些返回值来判断最终的认证状态。
对于FastAPI内置的认证方案,如HTTPBasic和OAuth2PasswordBearer,可以通过设置auto_error=False来实现这一目标。
2. 实现非阻塞式 Basic Authentication
首先,我们需要修改HTTPBasic实例,使其在缺少或无效的Basic Auth头时不会自动抛出401错误。
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi import Depends, HTTPException, status
from typing import Optional, Annotated
import secrets # 用于安全地比较字符串
# 假设 settings.SESSION_LOGIN_USER 和 settings.SESSION_LOGIN_PASS 存储了正确的用户名和密码
# 假设 router 和 db_session 已定义
# 假设 User 模型已定义
# 1. 初始化 HTTPBasic,设置 auto_error=False
security = HTTPBasic(auto_error=False)
# 2. 创建 Basic Auth 依赖函数
def basic_logged_user(credentials: Annotated[Optional[HTTPBasicCredentials], Depends(security)]):
"""
Basic Auth 认证依赖。
如果认证失败,不抛出异常,而是返回 None。
"""
if credentials is None:
# 没有提供 Basic Auth 凭据
return None
# 安全地比较用户名和密码
current_username_bytes = credentials.username.encode("utf8")
correct_username_bytes = settings.SESSION_LOGIN_USER.encode("utf8")
is_correct_username = secrets.compare_digest(current_username_bytes, correct_username_bytes)
current_password_bytes = credentials.password.encode("utf8")
correct_password_bytes = settings.SESSION_LOGIN_PASS.encode("utf8")
is_correct_password = secrets.compare_digest(current_password_bytes, correct_password_bytes)
if not (is_correct_username and is_correct_password):
# 凭据无效,返回 None
return None
# 认证成功,返回用户名
return credentials.username在这个basic_logged_user函数中:
- Depends(security)会尝试解析Basic Auth凭据。由于auto_error=False,如果凭据缺失,credentials将为None。
- 我们显式地将credentials声明为Optional[HTTPBasicCredentials],以处理None的情况。
- 无论凭据缺失还是无效,函数都返回None,而不是抛出HTTPException。
3. 实现非阻塞式 JWT Authentication
类似地,我们需要对JWT认证方案进行调整。通常,JWT认证会使用OAuth2PasswordBearer。我们也需要将其初始化为auto_error=False。
from fastapi.security import OAuth2PasswordBearer
# ... 其他导入 ...
# 假设 utils.verify_token 是一个验证JWT并返回用户数据的函数
# 假设 db_session 和 User 模型已定义
# 1. 初始化 OAuth2PasswordBearer,设置 auto_error=False
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token", auto_error=False) # tokenUrl 根据你的实际情况设置
# 2. 创建 JWT Auth 依赖函数
def jwt_logged_user(token: Annotated[Optional[str], Depends(oauth2_scheme)],
db: Session = Depends(db_session)):
"""
JWT Auth 认证依赖。
如果认证失败,不抛出异常,而是返回 None。
"""
if token is None:
# 没有提供 JWT token
return None
try:
# 假设 utils.verify_token 会验证 token 并返回一个包含用户信息的对象
# 如果 token 无效,utils.verify_token 内部应该捕获异常或返回 None
# 这里我们假设它在验证失败时会抛出异常,我们捕获它
payload = utils.verify_token(token) # 假设 verify_token 成功返回 payload,失败抛异常
username = payload.get("sub") # 假设 sub 字段存储用户名
if not username:
return None
user = db.query(User).filter(User.username == username).first()
if not user:
return None
return user # 认证成功,返回用户对象
except Exception:
# token 验证失败(过期、无效签名等)
return None在这个jwt_logged_user函数中:
美图云修
商业级AI影像处理工具
50
查看详情
- Depends(oauth2_scheme)会尝试从请求头中提取JWT token。由于auto_error=False,如果token缺失,token参数将为None。
- 我们同样将token声明为Optional[str]。
- utils.verify_token应该被设计为在验证失败时抛出异常或返回一个可识别的失败状态。这里我们用try-except块来捕获验证失败的情况,并返回None。
4. 创建组合认证依赖 (auth_user)
现在我们有了两个非阻塞式的认证依赖,可以创建一个新的依赖函数来组合它们,实现“或”逻辑。
from fastapi import HTTPException, status
# ... 其他导入 ...
def auth_user(jwt_auth_result: Annotated[Optional[User], Depends(jwt_logged_user)],
basic_auth_result: Annotated[Optional[str], Depends(basic_logged_user)]):
""&
quot;
组合认证依赖,支持 Basic Auth 或 JWT Auth。
如果任一认证方式成功,则返回相应的认证用户。
如果两种方式都失败,则抛出 401 异常。
"""
if jwt_auth_result:
# JWT 认证成功
return jwt_auth_result
if basic_auth_result:
# Basic Auth 认证成功
# 注意:这里返回的类型需要与 jwt_auth_result 的类型保持一致,
# 或者根据你的业务逻辑决定返回哪个。
# 为了简化,这里假设可以返回一个字符串作为认证成功的标识。
# 如果需要返回统一的用户对象,则需要从 basic_auth_result 中获取用户对象。
return basic_auth_result
# 两种认证方式都失败,抛出 401 未授权异常
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail='Invalid Credentials',
headers={"WWW-Authenticate": "Bearer, Basic"} # 提示客户端支持的认证方式
)在这个auth_user函数中:
- 它接收jwt_logged_user和basic_logged_user的返回值。
- 如果jwt_auth_result不为None(即JWT认证成功),则直接返回该结果。
- 否则,如果basic_auth_result不为None(即Basic Auth认证成功),则返回该结果。
- 只有当两种认证方式都返回None时,才抛出HTTP_401_UNAUTHORIZED异常。
5. 在API端点中使用组合认证
最后,将auth_user依赖添加到你的API端点中。
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
# ... 其他导入 ...
router = APIRouter() # 假设你有一个 APIRouter 实例
@router.get("/users")
async def get_users(db: Session = Depends(db_session),
logged_user: Annotated[Union[User, str], Depends(auth_user)]):
"""
获取用户列表,需要 Basic Auth 或 JWT Auth 认证。
"""
query_users = db.query(User).all()
return query_users现在,当客户端请求/users端点时:
- 如果提供了有效的JWT Bearer Token,即使没有提供Basic Auth,请求也会成功。
- 如果提供了有效的Basic Auth凭据,即使没有提供JWT Token,请求也会成功。
- 只有当两种认证方式的凭据都缺失或无效时,才会收到401 Unauthorized响应。
总结与注意事项
通过将各个认证依赖项配置为非阻塞模式(auto_error=False并返回None),并创建一个中央组合依赖来处理最终的授权逻辑,我们成功地实现了FastAPI中多重可选认证的需求。
注意事项:
- 返回类型统一: 在auth_user中,jwt_auth_result可能返回User对象,而basic_auth_result可能返回str(用户名)。在实际应用中,你可能希望将它们统一为某种形式的用户对象,例如通过用户名从数据库中加载用户对象,确保auth_user始终返回User类型或其接口类型。
- 错误信息: 在auth_user抛出HTTPException时,WWW-Authenticate头部应包含所有支持的认证方案,以便客户端知道如何进行认证。
- 安全性: 在实现认证逻辑时,务必使用secrets.compare_digest等安全函数来比较密码,以防止定时攻击。
- 可扩展性: 这种模式非常灵活,你可以轻松地添加更多可选的认证方案(如API Key认证),只需为每个方案创建非阻塞依赖,并在auth_user中进行组合。
通过遵循这些原则,你可以构建出既安全又灵活的FastAPI认证系统。
以上就是FastAPI实现多重可选认证:同时支持Basic Auth与JWT Auth的详细内容,更多请关注其它相关文章!
# 也会
# 博罗品牌网站建设报价
# 网站设计SEO优化万象
# 吴江企业网站优化找哪家
# 网站架构建设方法
# 巴中商城网站建设运营
# 山东关键词排名七天上线
# 西安定制网站seo优化
# 淘宝营销推广的方式包括
# 花都seo优化公司
# 名词解释:seo
# 使其
# 你可以
# word
# 美图
# 在这个
# 客户端
# 两种
# 可选
# 文档
# 抛出
# asic
# red
# 常见问题
# ai
# session
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台
“在文档元素之后找到了标记”是什么错误? 检查并修复XML中多个根元素的3个方法
单射、满射与双射的关系 一文理清所有逻辑
Win11 USB传输速度慢怎么解决 Win11 USB驱动更新与设置
冬*霸灯泡不亮怎么办_浴霸取暖灯一盏不亮的灯座清洁修复法
word邮件合并后日期格式不对怎么改_Word邮件合并日期格式修改方法
Excel组合图表怎么做 Excel创建柱状图与折线组合图教程【图表】
QQ邮箱稳定登录入口_QQ邮箱官方网站网页版使用
Node.js 中使用 node-cron 实现定时 API 数据抓取与处理
动漫岛观看全网网 动漫岛在线正版动漫入口
mysql通配符支持数字匹配吗_mysql通配符能否用于数字匹配的解析
蛙漫2台版漫画地址 Manwa2正版网页版链接
优化 Jest 模拟:强制未实现函数抛出错误以提升测试效率
excel怎么制作工资条 excel快速生成工资条的方法
在Qt QML中通过Python字典动态更新TextEdit内容的教程
微信商城在哪里打开【步骤】
PHP表单数据传递:如何通过隐藏输入字段获取动态ID
在命令行怎么运行html项目_命令行运行html项目方法【教程】
HuggingFaceEmbeddings中向量嵌入维度调整的限制与理解
Composer中的^和~符号代表什么_精通Composer版本号语义化约束
押井守高度称赞《辐射4》:玩了八年都停不下来!
Golang如何优化CPU绑定任务分配策略_Golang CPU任务分配优化实践
晋江读书网页版在线登录 晋江读书电脑版官网
win11 Snap Layouts怎么用 Win11窗口布局与分屏多任务高效指南【必学】
Angular响应式表单:实现提交后表单及按钮的禁用与只读化
HTML元素状态管理:根据DIV内容动态启用/禁用按钮
理解J*aScript Promise的微任务队列与执行顺序
解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南
qq音乐在线播放入口_qq音乐电脑版登录链接
AO3最新入口2025公告_AO3中文官网合集
Windows 11怎么彻底关闭定位_Windows 11服务中禁用Geolocation
React列表渲染与独立状态管理:避免全局状态影响局部更新
Python模块化编程:有效管理依赖与避免循环引用
msn官网入口地址手机版 msn官方网站手机最新链接
台积电1.4nm工艺A14瞄准2028:10年来性能提升80%
印象笔记如何设离线包出差查阅_印象笔记设离线包出差查阅【离线阅读】
漫蛙2漫画入口 漫蛙正版网页漫画直达网址
谷歌学术网站直达地址 谷歌学术搜索网页版一键进入
怎样使用“本地安全策略”提升Windows安全性_Secpol.msc配置指南【高手】
《GTA6》开发画面疑似泄露!这次可不是AI了
Linux如何排查内存不足OOME问题_LinuxOOM分析教程
印象笔记如何设提醒任务防漏执行_印象笔记设提醒任务防漏执行【任务提醒】
Spyder启动失败:字体文件权限拒绝错误解决方案
Go与Ruby之间实现AES加密互通:CFB模式下的密钥长度匹配策略
TikTok国际版网页端快速入口 TikTok全球版短视频浏览教程
从J*aScript对象中精确提取指定属性的教程
免费抖音短视频入口_抖音网页版短视频免费通道
如何将HTML表格多行数据保存到Google Sheets
一加Ace 6T实拍样张首次公布!李杰:主摄实力完全看齐4K档性能旗舰
在Runstone环境中高效处理TasteDive API的JSON数据


2025-11-26
浏览次数:次
返回列表
quot;
组合认证依赖,支持 Basic Auth 或 JWT Auth。
如果任一认证方式成功,则返回相应的认证用户。
如果两种方式都失败,则抛出 401 异常。
"""
if jwt_auth_result:
# JWT 认证成功
return jwt_auth_result
if basic_auth_result:
# Basic Auth 认证成功
# 注意:这里返回的类型需要与 jwt_auth_result 的类型保持一致,
# 或者根据你的业务逻辑决定返回哪个。
# 为了简化,这里假设可以返回一个字符串作为认证成功的标识。
# 如果需要返回统一的用户对象,则需要从 basic_auth_result 中获取用户对象。
return basic_auth_result
# 两种认证方式都失败,抛出 401 未授权异常
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail='Invalid Credentials',
headers={"WWW-Authenticate": "Bearer, Basic"} # 提示客户端支持的认证方式
)