from datetime import datetime, timedelta from typing import Optional from jose import JWTError, jwt from passlib.context import CryptContext from dotenv import load_dotenv import os # 加载环境变量 load_dotenv() # 密码加密上下文 pwd_context = CryptContext(schemes=["pbkdf2_sha256"], deprecated="auto") # JWT 配置 SECRET_KEY = os.getenv("SECRET_KEY", "your-secret-key") ALGORITHM = os.getenv("ALGORITHM", "HS256") ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "600")) def verify_password(plain_password, hashed_password): """验证密码""" return pwd_context.verify(plain_password, hashed_password) def get_password_hash(password): """获取密码哈希值""" # 限制密码长度不超过72字节,这是bcrypt的限制 if len(password) > 72: password = password[:72] return pwd_context.hash(password) def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): """创建访问令牌""" to_encode = data.copy() if expires_delta: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=15) to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) return encoded_jwt def decode_token(token: str): """解码令牌""" try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) username: str = payload.get("sub") if username is None: return None return username except JWTError: return None