本文详细阐述如何在FastAPI中实现灵活的多重认证机制,允许客户端通过Basic Auth或JWT Bearer Token中的任意一种方式访问受保护的API端点。核心策略是将各个认证依赖项配置为在认证失败时不立即抛出异常,而是返回None,从而将最终的授权决策和错误处理集中到一个高级组合依赖中。
在构建现代Web API时,常常需要支持多种认证方式以适应不同的客户端或使用场景。例如,某些内部服务可能使用Basic Auth,而外部客户端则可能依赖JWT。FastAPI的依赖注入系统非常强大,但默认情况下,当一个端点声明了多个认证依赖时,FastAPI会尝试强制所有依赖都成功。这导致了一个常见问题:如何让端点支持“或”逻辑,即只要任意一种认证方式成功即可访问?
本文将通过一个具体的示例,演示如何改造FastAPI的认证依赖,使其能够灵活地支持Basic Auth或JWT Auth的任选模式。
解决此问题的关键在于,让单个的认证依赖项在认证失败时不再立即抛出HTTPException,而是返回一个指示失败的值(通常是None)。这样,上层组合依赖就可以根据这些返回值来判断最终的认证状态。
对于FastAPI内置的认证方案,如HTTPBasic和OAuth2PasswordBearer,可以通过设置auto_error=False来实现这一目标。
首先,我们需要修改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函数中:
类似地,我们需要对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函数中:
现在我们有了两个非阻塞式的认证依赖,可以创建一个新的依赖函数来组合它们,实现“或”逻辑。
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)]):
"""
组合认证依赖,支持 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函数中:
最后,将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端点时:
通过将各个认证依赖项配置为非阻塞模式(auto_error=False并返回None),并创建一个中央组合依赖来处理最终的授权逻辑,我们成功地实现了FastAPI中多重可选认证的需求。
注意事项:
通过遵循这些原则,你可以构建出既安全又灵活的FastAPI认证系统。
# word
# session
# ai
# 常见问题
# red
# asic
# fastapi
# try
# Token
# 接口
# 对象
# 数据库
# 抛出
# 两种
# 客户端
# 在这个
# 也会
# 你可以
# 使其
# 可选
# 不为
# 将为
相关文章:
php8.4新语法match怎么用_php8.4match表达式替代switch【方法】
建站主机类型有哪些?如何正确选型
网站制作公司,橙子建站是合法的吗?
如何在阿里云虚拟主机上快速搭建个人网站?
制作网站的过程怎么写,用凡科建站如何制作自己的网站?
制作网站的软件免费下载,免费制作app哪个平台好?
武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?
广东专业制作网站有哪些,广东省能源集团有限公司官网?
如何处理“XML格式不正确”错误 常见XML well-formed问题解决方法
制作网站的模板软件,网站怎么建设?
,购物网站怎么盈利呢?
魔方云NAT建站如何实现端口转发?
如何高效利用亚马逊云主机搭建企业网站?
建站之星安装提示数据库无法连接如何解决?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
,南京靠谱的征婚网站?
安云自助建站系统如何快速提升SEO排名?
建站之星与建站宝盒如何选择最佳方案?
如何在建站宝盒中设置产品搜索功能?
开源网站制作软件,开源网站什么意思?
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
大学网站设计制作软件有哪些,如何将网站制作成自己app?
建站与域名管理如何高效结合?
如何在香港服务器上快速搭建免备案网站?
如何配置IIS站点权限与局域网访问?
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
如何高效配置IIS服务器搭建网站?
制作网站建设的公司有哪些,网站建设比较好的公司都有哪些?
北京制作网站的公司,北京铁路集团官方网站?
兔展官网 在线制作,怎样制作微信请帖?
建站主机选哪种环境更利于SEO优化?
如何在Golang中实现微服务服务拆分_Golang微服务拆分与接口管理方法
大连 网站制作,大连天途有线官网?
网站视频怎么制作,哪个网站可以免费收看好莱坞经典大片?
导航网站建站方案与优化指南:一站式高效搭建技巧解析
上海网站制作网页,上海本地的生活网站有哪些?最好包括生活的各个方面的?
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?
全景视频制作网站有哪些,全景图怎么做成网页?
如何选择靠谱的建站公司加盟品牌?
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
,怎么用自己头像做动态表情包?
如何在阿里云域名上完成建站全流程?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
建站IDE高效指南:快速搭建+SEO优化+自适应模板全解析
宠物网站制作html代码,有没有专门介绍宠物如何养的网站啊?
临沂网站制作公司有哪些,临沂第四中学官网?
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
长沙做网站要多少钱,长沙国安网络怎么样?
洛阳网站制作公司有哪些,洛阳的招聘网站都有哪些?
*请认真填写需求信息,我们会在24小时内与您取得联系。