diff --git a/src/pineagents/app/auth.py b/src/pineagents/app/auth.py index a11c3c5..2da469a 100644 --- a/src/pineagents/app/auth.py +++ b/src/pineagents/app/auth.py @@ -174,35 +174,56 @@ def verify_token(token: str) -> Optional[str]: """Verify *token*, return username if valid, ``None`` otherwise. Also checks if the token has been revoked (appears in the revocation list). + + 性能优化:验证结果缓存 30 秒,避免每次请求都重复 HMAC 验证和磁盘 I/O。 """ import base64 + # 性能优化:验证结果缓存(内存,30 秒 TTL) + global _token_verify_cache + if "_token_verify_cache" not in globals(): + _token_verify_cache = {} + now = time.time() + cached = _token_verify_cache.get(token) + if cached is not None and now < cached["expires_at"]: + return cached["result"] + try: parts = token.split(".", 1) if len(parts) != 2: - return None - payload_b64, sig = parts - secret = _get_jwt_secret() - expected_sig = hmac.new( - secret.encode(), - payload_b64.encode(), - hashlib.sha256, - ).hexdigest() - if not hmac.compare_digest(sig, expected_sig): - return None - payload = json.loads(base64.urlsafe_b64decode(payload_b64)) - if payload.get("exp", 0) < time.time(): - return None - - # Check if token is revoked - jti = payload.get("jti") - if jti and _is_token_revoked(jti): - return None - - return payload.get("sub") + result = None + else: + payload_b64, sig = parts + secret = _get_jwt_secret() + expected_sig = hmac.new( + secret.encode(), + payload_b64.encode(), + hashlib.sha256, + ).hexdigest() + if not hmac.compare_digest(sig, expected_sig): + result = None + else: + payload = json.loads(base64.urlsafe_b64decode(payload_b64)) + if payload.get("exp", 0) < now: + result = None + else: + # Check if token is revoked + jti = payload.get("jti") + if jti and _is_token_revoked(jti): + result = None + else: + result = payload.get("sub") except (json.JSONDecodeError, KeyError, ValueError, TypeError) as exc: logger.debug("Token verification failed: %s", exc) - return None + result = None + + # 写缓存(30 秒 TTL) + _token_verify_cache[token] = {"result": result, "expires_at": now + 30} + # 限制缓存大小,避免内存泄漏 + if len(_token_verify_cache) > 1000: + # 清理过期的缓存项 + _token_verify_cache = {k: v for k, v in _token_verify_cache.items() if time.time() < v["expires_at"]} + return result # ---------------------------------------------------------------------------