引用此链接: fastapi-supporting-multiple-authentication-dependencies

我认为这是最接近我需要的东西,但不知何故,我无法让这两个依赖项中的任何一个工作,因为Fastapi在授予对端点的访问权限之前会强制执行这两个依赖项.

用于定制需求的代码片段:

def basic_logged_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]):
    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):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid Credentials",
            headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username


def jwt_logged_user(token: str = Depends(utils.OAuth2_scheme), 
                    db: Session = Depends(db_session)):
    credential_exception = HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
                                         detail="Incorrect username or password",
                                         headers={"WWW-Authenticate": "Bearer"})

    token = utils.verify_token(token, credential_exception)
    user = db.query(User).filter(User.username == token.username).first()

    return user


# custom auth
def auth_user(jwt_auth: HTTPBearer = Depends(jwt_logged_user), 
                    basic_auth: HTTPBasic = Depends(basic_logged_user)):
    if not (jwt_auth or basic_auth):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, 
                            detail='Invalid Credentials')


#endpoint
@router.get("/")
async def get_users(db: Session = Depends(db_session), logged_user: str = Depends(auth_user)):
    query_users = db.query(User).all()

    return query_users

我希望当我为JWT身份验证或基本身份验证提供正确的凭据时,它会授予我访问终结点的权限,但它仍然强制我为这两种身份验证都输入凭据.我如何才能达到这样的效果:提供两个身份验证中的任何一个,而不是两个都提供.

推荐答案

我们的 idea 是使所有这些安全依赖项不会在依赖项解析阶段出现用户身份验证错误时引发异常.

对于HTTPBasic通过auto_error=False:

security = HTTPBasic(auto_error=False)

然后在basic_logged_user年你应该判断一下

def basic_logged_user(credentials: Annotated[Optional[HTTPBasicCredentials], Depends(security)]):
    if credentials is None:
        return None
    ...
    # Do not raise exception, but return None instead

您需要找到如何对您的第二个身份验证方案(utils.OAuth2_scheme)执行同样的操作--不是引发HTTP_401_UNAUTHORIZED,而是返回None.

那么你的auth_user就会像你预期的那样工作.只有在两个计划都返回None的情况下,它才会筹集HTTP_401_UNAUTHORIZED.

Python相关问答推荐

Python:根据创建时间合并两个收件箱

不同数据类型的Python成员变量不会在具有相同优先级的不同线程中更新

如何对行使用分段/部分.diff()或.pct_change()?

创建带有二维码的Flask应用程序,可重定向到特定端点

在Python中为变量的缺失值创建虚拟值

使用scipy. optimate.least_squares()用可变数量的参数匹配两条曲线

如何让 turtle 通过点击和拖动来绘制?

运行终端命令时出现问题:pip start anonymous"

在Python中管理打开对话框

为什么默认情况下所有Python类都是可调用的?

如何使用数组的最小条目拆分数组

Pandas—合并数据帧,在公共列上保留非空值,在另一列上保留平均值

如何让这个星型模式在Python中只使用一个for循环?

如何设置视频语言时上传到YouTube与Python API客户端

cv2.matchTemplate函数匹配失败

给定高度约束的旋转角解析求解

Asyncio:如何从子进程中读取stdout?

将pandas导出到CSV数据,但在此之前,将日期按最小到最大排序

Python—转换日期:价目表到新行

导入错误:无法导入名称';操作';