FastAPI中能否将HTTPBearer.credentials转换为Pydantic BaseModel?
问题描述
我正在用FastAPI的HTTPBearer类从请求头接收授权令牌,当前依赖逻辑是把token.credentials(JSON字符串)手动解析成自定义的ClassroomAuthCredentials模型。我希望能像定义请求体结构那样,直接指定token.credentials的数据结构——既方便直接访问属性,也能在Swagger的授权模态框里展示格式说明,让团队开发者不用猜测必填字段。
当前依赖代码:
classroom_auth_scheme = HTTPBearer( scheme_name="Google Auth Credentials", bearerFormat="Bearer", description="O-Auth2 Credentials obtained on frontend, used to authenticate with Google services", ) def get_classroom_token( token: str = Depends(classroom_auth_scheme), ) -> requests.ClassroomAuthCredentials: """Converts a json string of Authorization Bearer token into ClassroomAuthCredentials class Args: token (str, optional): Autorization Header Bearer Token. Defaults to Depends(auth_scheme). Raises: HTTPException: 400 level response meaning the token was not in the correct format Returns: requests.ClassroomAuthCredentials """ try: # token.credentials is a JSON String -> want: pydantic Basemodel token_dict = json.loads(token.credentials) token = requests.ClassroomAuthCredentials.parse_obj(token_dict) return token except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"{e}", )
路由使用方式:
@router.post("/test-auth", summary="Validate authentication with Google Classroom API") async def test_auth(token=Depends(get_classroom_token)): try: gc_service_test = get_service(token) gc_api_test = ClassroomApi(service=gc_service_test) user_profile = gc_api_test.get_user_profile("me") response: responses.ListGoogleClassroomCourses = { "message": f"Auth Credentials Are Valid", "userProfile": user_profile, } return JSONResponse(response) except errors.HttpError as error: # handle exceptions...
我已定义对应的BaseModel:
class ClassroomAuthCredentials(BaseModel): token: str = Field(..., example="MyJWT") clientId: str = Field(..., example="myClientId") clientSecret: str = Field(..., example="myClientSecret") refreshToken: str = Field(..., example="myRefreshToken") scopes: list[str] = Field( ..., example=[ "https://www.googleapis.com/auth/classroom.courses.readonly", "https://www.googleapis.com/auth/classroom.coursework.students", ], )
解决方案
完全可以实现,核心是自定义继承HTTPBearer的认证方案类,让它直接处理JSON到Pydantic模型的解析,同时把模型结构同步到Swagger文档中。
步骤1:自定义认证方案类
替换原有HTTPBearer实例,改为继承它的子类,重写__call__方法完成自动解析:
from fastapi import HTTPException, status, Depends from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from pydantic import ValidationError import json class ClassroomAuthScheme(HTTPBearer): def __init__(self): super().__init__( scheme_name="Google Auth Credentials", bearerFormat="Bearer", description="O-Auth2 Credentials obtained on frontend, used to authenticate with Google services. Format: JSON string matching ClassroomAuthCredentials schema", ) async def __call__(self, request): credentials: HTTPAuthorizationCredentials = await super().__call__(request) try: # 直接将凭证解析为Pydantic模型 token_data = ClassroomAuthCredentials.parse_raw(credentials.credentials) return token_data except (json.JSONDecodeError, ValidationError) as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Invalid token format: {str(e)}" ) # 创建认证方案实例 classroom_auth_scheme = ClassroomAuthScheme() # 简化依赖函数,直接返回模型实例 def get_classroom_token( token: ClassroomAuthCredentials = Depends(classroom_auth_scheme), ) -> ClassroomAuthCredentials: return token
步骤2:更新路由使用
路由无需大幅修改,token现在已是ClassroomAuthCredentials实例,可直接访问属性:
@router.post("/test-auth", summary="Validate authentication with Google Classroom API") async def test_auth(token: ClassroomAuthCredentials = Depends(get_classroom_token)): try: # 直接使用token.token、token.clientId等属性 gc_service_test = get_service(token) gc_api_test = ClassroomApi(service=gc_service_test) user_profile = gc_api_test.get_user_profile("me") response = { "message": "Auth Credentials Are Valid", "userProfile": user_profile, } return JSONResponse(response) except errors.HttpError as error: # 异常处理逻辑 ...
步骤3:优化Swagger文档展示
在认证方案的description中添加Markdown格式的示例,让开发者在授权模态框里直接看到格式要求:
description="""O-Auth2 Credentials obtained on frontend, used to authenticate with Google services. **Required JSON Format**: ```json { "token": "MyJWT", "clientId": "myClientId", "clientSecret": "myClientSecret", "refreshToken": "myRefreshToken", "scopes": [ "https://www.googleapis.com/auth/classroom.courses.readonly", "https://www.googleapis.com/auth/classroom.coursework.students" ] } ```""",
核心优势
- 无需手动调用
json.loads和parse_obj,Pydantic自动完成验证与解析 - 直接通过模型属性访问数据,代码更简洁
- Swagger文档自动展示格式要求,降低团队协作成本
- 验证错误信息更精准,包含Pydantic的字段级提示
内容的提问来源于stack exchange,提问作者Rafael Zasas
相关产品推荐
相关产品推荐

