You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI实现二选一依赖注入:登录或API Key认证访问受保护路由

解决FastAPI双认证二选一的正确姿势

你之前的两种写法都存在问题:

  • 第一个写法重复定义user参数,不符合Python语法,FastAPI也无法处理同名依赖
  • 第二个写法直接在路由函数内调用Security()和Depends()是错误的,这两个是声明依赖的工具,不能直接在函数内部执行

FastAPI确实有官方推荐的多认证兼容方案,核心是自定义组合依赖,在这个依赖里依次尝试两种认证方式,只要其中一种成功就返回用户,都失败再抛出认证错误。

具体实现步骤:

  1. 导入必要模块:
from fastapi import Depends, HTTPException, status
from fastapi_users import current_active_user
from your_auth_module import get_user_from_api_key, User
  1. 编写自定义组合依赖函数:
async def get_current_user_or_api_key_user(
    user_from_auth: User = Depends(current_active_user),
    user_from_api_key: User = Depends(get_user_from_api_key)
):
    # 优先尝试用户登录认证
    try:
        return user_from_auth
    except HTTPException as e:
        # 仅捕获认证失败的401异常,其他错误直接抛出
        if e.status_code != status.HTTP_401_UNAUTHORIZED:
            raise e
        # 尝试API Key认证
        try:
            return user_from_api_key
        except HTTPException:
            # 两种认证都失败,抛出统一的401提示
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="请提供有效的用户认证令牌或API Key",
                headers={"WWW-Authenticate": "Bearer, ApiKey"},
            )

注意:这里假设current_active_user和get_user_from_api_key在认证失败时都会抛出HTTPException(401),如果你的API Key依赖抛出的异常类型不同,需要调整捕获逻辑。

  1. 在路由中使用这个自定义依赖:
@router.get('/protected')
def wrapper_layout(
    layoutRun: LayoutRun,
    user: User = Depends(get_current_user_or_api_key_user)
):
    # 此处的user已通过任意一种认证方式获取,可直接用于业务逻辑
    return {"user_id": user.id, "message": "访问受保护路由成功"}

如果你的两个依赖在认证失败时会返回None而非抛出异常,还可以用更简洁的写法:

async def get_current_user_or_api_key_user(
    user_from_auth: User | None = Depends(current_active_user),
    user_from_api_key: User | None = Depends(get_user_from_api_key)
):
    if user_from_auth:
        return user_from_auth
    if user_from_api_key:
        return user_from_api_key
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="请提供有效的用户认证令牌或API Key",
        headers={"WWW-Authenticate": "Bearer, ApiKey"},
    )

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 01:17:35