""" 依赖注入工具 ============ """ from __future__ import annotations from fastapi import Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.config import get_settings from app.core.security import verify_token from app.db.session import get_db as db_session from app.models.user import User settings = get_settings() security = HTTPBearer(auto_error=False) # 数据库依赖 async def get_db() -> AsyncSession: """获取数据库 Session""" async for session in db_session(): yield session async def get_current_user( credentials: HTTPAuthorizationCredentials | None = Depends(security), db: AsyncSession = Depends(get_db), ) -> User: """ 获取当前登录用户 从 Authorization Header 中提取 JWT Token 并验证 """ if credentials is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="缺少认证信息", headers={"WWW-Authenticate": "Bearer"}, ) token = credentials.credentials payload = verify_token(token) if payload is None or payload.get("sub") is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="无效的认证信息", headers={"WWW-Authenticate": "Bearer"}, ) user_id = payload.get("sub") result = await db.execute(select(User).where(User.id == user_id)) user = result.scalar_one_or_none() if user is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="用户不存在", headers={"WWW-Authenticate": "Bearer"}, ) return user async def get_current_user_optional( credentials: HTTPAuthorizationCredentials | None = Depends(security), db=Depends(get_db), ) -> User | None: """ 获取当前登录用户(可选,未登录返回 None) """ if credentials is None: return None try: return await get_current_user(credentials, db) except HTTPException: return None