""" 内部服务鉴权:验证来自 java-mock 的请求签名。 签名算法(与 java-mock/middleware/internalSign.js 保持一致): message = "java-gateway:{userId}:{毫秒时间戳}" signature = HMAC-SHA256(INTERNAL_SERVICE_SECRET, message) # hex """ import hashlib import hmac import os import time # 允许的时钟偏差(毫秒),防重放攻击 _ALLOWED_SKEW_MS = 5 * 60 * 1000 # 5 分钟 def verify_internal_request(headers) -> bool: """ 验证内部服务请求签名。 未配置 INTERNAL_SERVICE_SECRET 时直接放行(开发/测试环境兼容)。 """ secret = os.environ.get("INTERNAL_SERVICE_SECRET", "") if not secret: return True service = headers.get("X-Internal-Service", "") user_id = headers.get("X-Internal-User-Id", "") timestamp = headers.get("X-Internal-Timestamp", "") signature = headers.get("X-Internal-Signature", "") # 基础字段校验 if service != "java-gateway" or not user_id or not timestamp or not signature: return False # 时间窗口校验(防重放) try: ts_ms = int(timestamp) if abs(int(time.time() * 1000) - ts_ms) > _ALLOWED_SKEW_MS: return False except ValueError: return False # 重新计算签名,使用常量时间比较防时序攻击 message = f"java-gateway:{user_id}:{timestamp}" expected = hmac.new( secret.encode("utf-8"), message.encode("utf-8"), hashlib.sha256, ).hexdigest() return hmac.compare_digest(expected, signature)