dingdanquanliucheng/backend/app/core/security.py

46 lines
1.6 KiB
Python

import base64
import hashlib
import hmac
import json
from datetime import datetime, timedelta, timezone
from backend.app.core.config import get_settings
settings = get_settings()
def hash_password(password: str) -> str:
secret = settings.secret_key.encode("utf-8")
return hashlib.sha256(secret + password.encode("utf-8")).hexdigest()
def verify_password(password: str, password_hash: str) -> bool:
return hmac.compare_digest(hash_password(password), password_hash or "")
def create_access_token(payload: dict) -> str:
data = dict(payload)
expire_at = datetime.now(timezone.utc) + timedelta(minutes=settings.jwt_expire_minutes)
data["exp"] = int(expire_at.timestamp())
body = json.dumps(data, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
body_b64 = base64.urlsafe_b64encode(body).decode("utf-8").rstrip("=")
signature = hmac.new(settings.secret_key.encode("utf-8"), body_b64.encode("utf-8"), hashlib.sha256).hexdigest()
return f"{body_b64}.{signature}"
def decode_access_token(token: str) -> dict | None:
try:
body_b64, signature = token.split(".", 1)
expected = hmac.new(settings.secret_key.encode("utf-8"), body_b64.encode("utf-8"), hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected):
return None
padded = body_b64 + "=" * (-len(body_b64) % 4)
payload = json.loads(base64.urlsafe_b64decode(padded.encode("utf-8")).decode("utf-8"))
exp = int(payload.get("exp", 0))
if exp <= int(datetime.now(timezone.utc).timestamp()):
return None
return payload
except Exception:
return None