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

FastAPI实现同时支持密码用户与Google用户的认证依赖注入

解决方案

核心思路

你不需要被OAuth2PasswordBearer绑定死,它本质上只是一个从请求头提取Authorization: Bearer xxx格式token的依赖,你完全可以自己控制token的解析逻辑,只要两种登录方式签发的JWT payload里带统一的用户标识和登录类型字段就行。

具体实现步骤

  • 第一步:统一两种登录成功后的JWT payload结构
    不管是密码登录还是Google登录,签发JWT的时候都在payload里加user_id、login_type(取值为password/google)两个固定字段,其他自定义字段按需添加即可,签名秘钥两种登录方式可以共用同一个,也可以分开,解析的时候对应判断就行。
  • 第二步:自定义token提取依赖
    不用纠结OAuth2PasswordBearer的tokenUrl参数,这个参数只在FastAPI自带的交互式文档里的「授权」按钮有用,不影响实际接口逻辑,你可以直接写自定义依赖提取token,示例:
    from fastapi import Request, HTTPException, status
    from typing import Optional
    
    def get_token_from_header(request: Request) -> str:
        auth_header = request.headers.get("Authorization")
        if not auth_header or not auth_header.startswith("Bearer "):
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="无效的认证凭证",
                headers={"WWW-Authenticate": "Bearer"},
            )
        return auth_header.split(" ")[1]
    
  • 第三步:实现通用的get_logged_in_user依赖
    from jose import JWTError, jwt
    from your_module import get_user_by_id # 替换为你自己的从数据库查询用户的方法
    
    # 替换为你自己的JWT配置
    SECRET_KEY = "your-secret-key"
    ALGORITHM = "HS256"
    
    async def get_logged_in_user(token: str = Depends(get_token_from_header)):
        credentials_exception = HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无法验证凭证",
            headers={"WWW-Authenticate": "Bearer"},
        )
        try:
            payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
            user_id: str = payload.get("user_id")
            login_type: str = payload.get("login_type")
            if user_id is None or login_type not in ["password", "google"]:
                raise credentials_exception
        except JWTError:
            raise credentials_exception
        user = await get_user_by_id(user_id)
        if user is None:
            raise credentials_exception
        # 可把login_type挂载到user对象返回,后续业务需要可以直接调用
        user.login_type = login_type
        return user
    

注意:不要在JWT里存敏感信息比如用户密码、Google的access_token,只存非敏感的标识字段即可。

可选优化

如果你还要保留FastAPI交互式文档的授权功能,不需要自定义token提取依赖,还是用OAuth2PasswordBearer,只需要把它的tokenUrl改成你密码登录的端点就行,Google登录的用户在前端拿到token之后,直接在交互式文档的授权弹窗里填token即可,完全不影响实际鉴权逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:21:01