feat(gateway): 为52号接口增加客户端静态Token校验
请求头X-API-Token默认yonghe1999,可通过interface52_token覆盖;缺少或不匹配返回401/code1009,不进入派发队列。客户端Token不转发到worker,其他接口保持原样。 同步Token输入框、配置示例与调用文档。57项网关测试及临时网关连接真实worker的浏览器验证通过。
This commit is contained in:
+18
-2
@@ -6,13 +6,14 @@
|
||||
|
||||
import asyncio
|
||||
import base64
|
||||
import hmac
|
||||
import json
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI, File, Form, Request, UploadFile
|
||||
from fastapi import FastAPI, File, Form, Header, Request, UploadFile
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
@@ -674,12 +675,27 @@ async def hairline_generate(request: Request):
|
||||
|
||||
@app.post("/api/v1/hairline/generate-52", tags=["人脸分析"],
|
||||
summary="接口52:发际线新规则与人像裁切")
|
||||
async def hairline_generate_52(request: Request):
|
||||
async def hairline_generate_52(
|
||||
request: Request,
|
||||
api_token: Optional[str] = Header(default=None, alias="X-API-Token",
|
||||
description="52号接口客户端Token,默认yonghe1999"),
|
||||
):
|
||||
"""透传图片三选一、gender、hair_style及normalize_image等参数至GPU worker。
|
||||
|
||||
worker负责中下庭均值定位、扶正裁切和生发;网关沿用原有派发、鉴权与图片URL改写。
|
||||
空图片保持原有 *_base64: null 字段。接口5保持原样。
|
||||
客户端须传X-API-Token;缺少或不匹配时返回HTTP401/code1009,不进入派发队列。
|
||||
"""
|
||||
from uuid import uuid4
|
||||
from gateway.config import DEFAULTS, get_config
|
||||
|
||||
expected = get_config().get("interface52_token", DEFAULTS["interface52_token"])
|
||||
if (not isinstance(expected, str) or not expected or not api_token
|
||||
or not hmac.compare_digest(api_token.encode("utf-8"), expected.encode("utf-8"))):
|
||||
return JSONResponse(status_code=401, content={
|
||||
"code": 1009, "message": "未授权:缺少或错误的 X-API-Token",
|
||||
"request_id": f"gw-{uuid4().hex[:8]}", "data": None,
|
||||
})
|
||||
return await _proxy(request, "/api/v1/hairline/generate-52")
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"interface52_token": "yonghe1999",
|
||||
"workers": [
|
||||
"http://127.0.0.1:28187",
|
||||
"http://127.0.0.1:28188"
|
||||
|
||||
@@ -13,6 +13,7 @@ logger = logging.getLogger("gateway.config")
|
||||
CONFIG_PATH = Path(__file__).resolve().parent / "config.json"
|
||||
|
||||
DEFAULTS = {
|
||||
"interface52_token": "yonghe1999",
|
||||
"public_base_url": "https://hair.xiangsilian.com",
|
||||
"static_dir": "static/annotations",
|
||||
"primary_workers": [], # 主 worker 地址列表(须为 workers 的子集);空 = 全部视为主 worker
|
||||
@@ -76,6 +77,10 @@ def load_config() -> dict:
|
||||
cfg = _deep_merge(DEFAULTS, raw)
|
||||
|
||||
# --- 校验 ---
|
||||
client_token = cfg["interface52_token"]
|
||||
if not isinstance(client_token, str) or not client_token:
|
||||
raise ValueError("配置错误: interface52_token 必须是非空字符串")
|
||||
|
||||
workers: List[str] = cfg.get("workers", [])
|
||||
if not workers:
|
||||
raise ValueError("配置错误: workers 列表不能为空,至少需要一个 worker 地址")
|
||||
|
||||
Reference in New Issue
Block a user