"""认证:密码哈希、令牌签发/校验、短信验证码(兼容原 mock 方案)""" import base64 import hashlib import json import time import random import re SECRET = "pine-mock-secret-2026" TOKEN_TTL_MS = 1000 * 60 * 60 * 12 # 12h PHONE_RE = re.compile(r"^1\d{10}$") CODE_TTL = 5 * 60 # 5 min # 演示环境:内存验证码 map(phone -> {code, exp}),响应返回 debugCode sms_codes: dict[str, dict] = {} def hash_password(s: str) -> str: return hashlib.sha256(str(s).encode()).hexdigest() def b64url(data: bytes) -> str: return base64.urlsafe_b64encode(data).rstrip(b"=").decode() def make_token(username: str) -> str: payload = b64url(json.dumps({"username": username, "exp": int(time.time() * 1000) + TOKEN_TTL_MS}).encode()) sig = b64url((SECRET + "." + payload).encode()) return f"{payload}.{sig}" def verify_token(token: str): if not token or not isinstance(token, str): return None parts = token.split(".") if len(parts) != 2: return None payload_part, sig_part = parts if b64url((SECRET + "." + payload_part).encode()) != sig_part: return None try: payload = json.loads(base64.urlsafe_b64decode(payload_part + "=" * (-len(payload_part) % 4)).decode()) if not payload.get("exp") or payload["exp"] < time.time() * 1000: return None return {"username": payload["username"]} except Exception: return None def send_sms_code(phone: str) -> str: code = str(random.randint(100000, 999999)) sms_codes[phone] = {"code": code, "exp": time.time() + CODE_TTL} return code def check_sms_code(phone: str, code: str) -> bool: rec = sms_codes.get(phone) if not rec or rec["code"] != str(code) or time.time() > rec["exp"]: return False sms_codes.pop(phone, None) return True