import jwt from datetime import datetime, timedelta from typing import AsyncGenerator, Optional from fastapi import Depends, HTTPException, Header, status from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker from app.config import settings # Database Engine & Session engine = create_async_engine( settings.DATABASE_URL, echo=settings.DEBUG, future=True, pool_pre_ping=True ) AsyncSessionLocal = async_sessionmaker( bind=engine, class_=AsyncSession, expire_on_commit=False, autocommit=False, autoflush=False, ) async def get_db_session() -> AsyncGenerator[AsyncSession, None]: async with AsyncSessionLocal() as session: try: yield session await session.commit() except Exception: await session.rollback() raise def create_access_token(address: str) -> str: expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES) payload = {"sub": address.lower(), "exp": expire} return jwt.encode(payload, settings.JWT_SECRET, algorithm=settings.JWT_ALGORITHM) async def get_current_user(authorization: Optional[str] = Header(None)) -> str: if not authorization or not authorization.startswith("Bearer "): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="缺少有效的认证 Token", headers={"WWW-Authenticate": "Bearer"}, ) token = authorization.split(" ")[1] try: payload = jwt.decode(token, settings.JWT_SECRET, algorithms=[settings.JWT_ALGORITHM]) address = payload.get("sub") if not address: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="无效的用户凭证") return address except jwt.PyJWTError: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token 已过期或无效")