from datetime import datetime, timedelta, timezone import importlib.util from fastapi import Depends, HTTPException, status from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer _jose_spec = importlib.util.find_spec("jose") _jose_origin = _jose_spec.origin if _jose_spec else None _incompatible_jose = bool(_jose_origin and _jose_origin.endswith("site-packages/jose.py")) try: import jwt from jwt import InvalidTokenError as JWTError except Exception as exc: if not _incompatible_jose: try: from jose import JWTError, jwt except Exception as fallback_exc: raise RuntimeError( "JWT 依赖不可用,请安装 python-jose[cryptography] 或 PyJWT" ) from fallback_exc else: raise RuntimeError( "检测到不兼容依赖 jose,请卸载 jose 后安装 python-jose[cryptography] 或安装 PyJWT" ) from exc from backend.config import settings security = HTTPBearer() def create_access_token(subject: str) -> str: expire = datetime.now(timezone.utc) + timedelta(minutes=settings.access_token_expire_minutes) payload = {"sub": subject, "exp": expire} return jwt.encode(payload, settings.jwt_secret_key, algorithm=settings.jwt_algorithm) def verify_password(username: str, password: str) -> bool: return username == settings.admin_username and password == settings.admin_password def get_current_user( credentials: HTTPAuthorizationCredentials = Depends(security), ) -> str: token = credentials.credentials try: payload = jwt.decode(token, settings.jwt_secret_key, algorithms=[settings.jwt_algorithm]) username: str | None = payload.get("sub") if not username: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="无效Token") return username except JWTError as exc: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="登录已过期") from exc