Files
2026-09-02 17:31:52 +08:00

81 lines
2.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""鼎捷云 IAM token 鉴权服务
通过调用 IAM `/api/iam/v2/identity/token/analyze` 校验请求头中的
digi-middleware-auth-user / digi-middleware-auth-app,解析出用户信息。
进程内 LRU 缓存(userToken -> userInfo),TTL 由 IAM_CACHE_TTL 控制,
减少对 IAM 的重复调用。
"""
import time
import httpx
from .config import settings
# httpx 异步客户端(进程级单例,复用连接池)
_http_client: httpx.AsyncClient | None = None
# 缓存:userToken -> (user_info, fetched_at)
_cache: dict[str, tuple[dict | None, float]] = {}
def _get_http_client() -> httpx.AsyncClient:
global _http_client
if _http_client is None:
_http_client = httpx.AsyncClient(timeout=5.0)
return _http_client
async def close_iam_client() -> None:
"""关闭 httpx 客户端(进程退出时调用)。"""
global _http_client
if _http_client is not None:
await _http_client.aclose()
_http_client = None
async def analyze_token(user_token: str, app_token: str | None = None) -> dict | None:
"""校验 IAM userToken,返回用户信息 dict 或 None。
调用 POST {IAM_BASE_URL}/api/iam/v2/identity/token/analyze,
请求头携带 digi-middleware-auth-app 与 digi-middleware-auth-user。
成功时返回包含 id/name/tenantId/tenantName 等字段的 dict。
"""
# 1. 查缓存
now = time.time()
cached = _cache.get(user_token)
if cached is not None and (now - cached[1]) < settings.IAM_CACHE_TTL:
return cached[0]
# 2. 调用 IAM analyze
headers = {
"digi-middleware-auth-user": user_token,
"digi-middleware-auth-app": app_token or settings.IAM_APP_TOKEN,
}
try:
client = _get_http_client()
resp = await client.post(
f"{settings.IAM_BASE_URL}/api/iam/v2/identity/token/analyze",
headers=headers,
)
except Exception as ex:
# IAM 不可达,缓存短时间避免雪崩
_cache[user_token] = (None, now)
print(f"[IAM] analyze 请求异常: {ex}")
return None
if resp.status_code == 200:
data = resp.json()
# 兼容字段:id(用户标识)/ name(姓名)
if data.get("id") or data.get("name"):
_cache[user_token] = (data, now)
return data
# 返回体无用户标识,视为无效
_cache[user_token] = (None, now)
return None
# 非 200(token 无效/过期),缓存避免雪崩
_cache[user_token] = (None, now)
return None