auth.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. # -*- coding: utf-8 -*-
  2. """JWT 实现学生与教师角色细粒度权限控制"""
  3. from datetime import datetime, timedelta
  4. from typing import Optional
  5. from jose import JWTError, jwt
  6. from fastapi import Depends, HTTPException, status
  7. from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials, APIKeyHeader
  8. from backend.config import get_settings
  9. settings = get_settings()
  10. security = HTTPBearer(auto_error=False)
  11. def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
  12. to_encode = data.copy()
  13. expire = datetime.utcnow() + (expires_delta or timedelta(minutes=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES))
  14. to_encode.update({"exp": expire})
  15. return jwt.encode(to_encode, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM)
  16. def decode_token(token: str) -> Optional[dict]:
  17. try:
  18. return jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=[settings.JWT_ALGORITHM])
  19. except JWTError:
  20. return None
  21. async def get_current_user_id(credentials: HTTPAuthorizationCredentials = Depends(security)) -> int:
  22. if credentials is None:
  23. raise HTTPException(status_code=401, detail="需要登录")
  24. payload = decode_token(credentials.credentials)
  25. if payload is None:
  26. raise HTTPException(status_code=401, detail="token 无效")
  27. uid = payload.get("sub")
  28. if uid is None:
  29. raise HTTPException(status_code=401, detail="token 无效")
  30. return int(uid)
  31. async def get_current_user_role(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str:
  32. if credentials is None:
  33. return "student"
  34. payload = decode_token(credentials.credentials)
  35. if payload is None:
  36. return "student"
  37. return payload.get("role", "student")
  38. def require_teacher(role: str = Depends(get_current_user_role)):
  39. if role != "teacher":
  40. raise HTTPException(status_code=403, detail="需要教师权限")
  41. return role