"""Token 鉴权:每个请求带 X-Bridge-Token header,bridge 校验。 设计(spec §6): - bridge 从环境变量 BRIDGE_TOKEN 读期望值,不进 git。 - 不符/缺失 -> 401。 - /health 豁免(该路由不挂 Depends(verify_token))。 - 使用 hmac.compare_digest 防时序攻击。 """ import hmac import logging import os from fastapi import HTTPException, Request logger = logging.getLogger(__name__) def get_expected_token() -> str | None: """从环境变量读 BRIDGE_TOKEN。""" return os.environ.get("BRIDGE_TOKEN") def verify_token(request: Request) -> None: """FastAPI Depends:校验 X-Bridge-Token header。 Raises: HTTPException 503: BRIDGE_TOKEN 未配置(安全默认:拒绝所有受保护请求)。 HTTPException 401: token 缺失或不匹配。 """ expected = get_expected_token() if not expected: # 未配置 token -> 拒绝所有受保护请求(不裸奔) raise HTTPException( status_code=503, detail="BRIDGE_TOKEN 环境变量未配置,拒绝服务", ) token = request.headers.get("X-Bridge-Token", "") if not hmac.compare_digest(token, expected): logger.warning( "token 校验失败 source=%s", request.client.host if request.client else "unknown", ) raise HTTPException(status_code=401, detail="token 无效")