diff --git a/mcp-auth/Dockerfile b/mcp-auth/Dockerfile index 1d11e80..a745120 100644 --- a/mcp-auth/Dockerfile +++ b/mcp-auth/Dockerfile @@ -25,7 +25,7 @@ COPY backend/app ./app COPY --from=frontend-build /app/frontend/dist ./app/static WORKDIR /app -EXPOSE 8000 +EXPOSE 9000 # STATIC_DIR 指向后端 app/static(相对 backend 启动目录) ENV STATIC_DIR=/app/app/static -CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] +CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "9000"] diff --git a/mcp-auth/backend/app/core/config.py b/mcp-auth/backend/app/core/config.py index 322479d..5e93fd1 100644 --- a/mcp-auth/backend/app/core/config.py +++ b/mcp-auth/backend/app/core/config.py @@ -4,7 +4,7 @@ import os class Settings: - AUTH_DB_HOST: str = os.getenv("AUTH_DB_HOST", "127.0.0.1") + AUTH_DB_HOST: str = os.getenv("AUTH_DB_HOST", "47.101.220.40") AUTH_DB_PORT: int = int(os.getenv("AUTH_DB_PORT", "5432")) AUTH_DB_USER: str = os.getenv("AUTH_DB_USER", "postgres") AUTH_DB_PASSWORD: str = os.getenv("AUTH_DB_PASSWORD", "digiwin") @@ -24,7 +24,7 @@ class Settings: STATIC_DIR: str = os.getenv("STATIC_DIR", "../frontend/dist") # Redis 配置 - REDIS_HOST: str = os.getenv("REDIS_HOST", "127.0.0.1") + REDIS_HOST: str = os.getenv("REDIS_HOST", "47.101.220.40") REDIS_PORT: int = int(os.getenv("REDIS_PORT", "6379")) REDIS_DB: int = int(os.getenv("REDIS_DB", "0")) REDIS_PASSWORD: str = os.getenv("REDIS_PASSWORD", "digiwin") diff --git a/mcp-auth/backend/app/core/redis.py b/mcp-auth/backend/app/core/redis.py index 62c2220..39ab0cd 100644 --- a/mcp-auth/backend/app/core/redis.py +++ b/mcp-auth/backend/app/core/redis.py @@ -39,9 +39,12 @@ async def close_redis() -> None: async def cache_get(key: str) -> dict | None: - """读取 JSON 缓存,返回 dict 或 None。""" - r = await get_redis() - raw = await r.get(key) + """读取 JSON 缓存,返回 dict 或 None。Redis 不可用时返回 None(视为缓存未命中)。""" + try: + r = await get_redis() + raw = await r.get(key) + except Exception: + return None if raw is None: return None try: @@ -51,14 +54,20 @@ async def cache_get(key: str) -> dict | None: async def cache_set(key: str, value: dict, ttl: int) -> None: - """写入 JSON 缓存,带 TTL(秒)。""" - r = await get_redis() - await r.setex(key, ttl, json.dumps(value)) + """写入 JSON 缓存,带 TTL(秒)。Redis 不可用时静默跳过。""" + try: + r = await get_redis() + await r.setex(key, ttl, json.dumps(value)) + except Exception: + pass async def cache_delete(*keys: str) -> None: - """删除缓存 key。""" + """删除缓存 key。Redis 不可用时静默跳过,缓存会自然过期。""" if not keys: return - r = await get_redis() - await r.delete(*keys) + try: + r = await get_redis() + await r.delete(*keys) + except Exception: + pass diff --git a/mcp-auth/backend/app/routers/tokens.py b/mcp-auth/backend/app/routers/tokens.py index 09c094b..d84ff45 100644 --- a/mcp-auth/backend/app/routers/tokens.py +++ b/mcp-auth/backend/app/routers/tokens.py @@ -17,7 +17,7 @@ router = APIRouter(prefix="/api/tokens", tags=["tokens"]) class TokenCreate(BaseModel): client_id: str - service_scope: str = "both" + service_scope: str description: str | None = None expires_at: datetime | None = None # null = 永不过期 @@ -77,14 +77,13 @@ async def list_tokens( async def create_token(req: TokenCreate, admin: dict = Depends(current_admin)): pool = await get_pool() - # 动态校验 service_scope:both 始终有效,其他值必须是已注册的 active 服务 - if req.service_scope != "both": - exists = await pool.fetchval( - "SELECT 1 FROM mcp_service WHERE service_name = $1 AND status = 'active'", - req.service_scope, - ) - if not exists: - raise HTTPException(400, f"service_scope '{req.service_scope}' 不是已注册的活跃服务") + # 动态校验 service_scope:必须是已注册的 active 服务 + exists = await pool.fetchval( + "SELECT 1 FROM mcp_service WHERE service_name = $1 AND status = 'active'", + req.service_scope, + ) + if not exists: + raise HTTPException(400, f"service_scope '{req.service_scope}' 不是已注册的活跃服务") # client_id 唯一校验:同一 client_id 不允许重复签发 existing = await pool.fetchval( diff --git a/mcp-auth/backend/app/routers/verify.py b/mcp-auth/backend/app/routers/verify.py index ecfbbec..ce86c52 100644 --- a/mcp-auth/backend/app/routers/verify.py +++ b/mcp-auth/backend/app/routers/verify.py @@ -108,7 +108,7 @@ async def verify_token(req: VerifyReq, service: str = Depends(_resolve_service)) return VerifyResp(valid=False) # 校验服务范围 scope = cached.get("service_scope") - if scope != "both" and scope != service: + if scope != service: return VerifyResp(valid=False) # 异步更新 last_used pool = await get_pool() @@ -146,9 +146,9 @@ async def verify_token(req: VerifyReq, service: str = Depends(_resolve_service)) if row["expires_at"] is not None and row["expires_at"].timestamp() < datetime.now(timezone.utc).timestamp(): return VerifyResp(valid=False) - # 服务范围校验:both 放行所有;否则要求精确匹配 + # 服务范围校验:要求精确匹配 scope = row["service_scope"] - if scope != "both" and scope != service: + if scope != service: return VerifyResp(valid=False) # 异步更新 last_used_at / last_used_svc diff --git a/mcp-auth/frontend/src/pages/Services/index.tsx b/mcp-auth/frontend/src/pages/Services/index.tsx index e1705fb..ee02183 100644 --- a/mcp-auth/frontend/src/pages/Services/index.tsx +++ b/mcp-auth/frontend/src/pages/Services/index.tsx @@ -57,9 +57,14 @@ export default function Services() { okType: 'danger', cancelText: '取消', onOk: async () => { - await revokeService(id); - message.success('已吊销'); - load(); + try { + await revokeService(id); + message.success('已吊销'); + } catch (e: any) { + message.error(e?.response?.data?.detail || '吊销失败'); + } finally { + load(); + } }, }); }; @@ -78,9 +83,14 @@ export default function Services() { okType: 'danger', cancelText: '取消', onOk: async () => { - await deleteService(id); - message.success('已删除'); - load(); + try { + await deleteService(id); + message.success('已删除'); + } catch (e: any) { + message.error(e?.response?.data?.detail || '删除失败'); + } finally { + load(); + } }, }); }; @@ -104,7 +114,7 @@ export default function Services() { }; const columns: ColumnsType = [ - { title: '服务名', dataIndex: 'service_name', key: 'service_name', width: 120 }, + { title: '服务名', dataIndex: 'service_name', key: 'service_name', width: 240 }, { title: 'API Key', dataIndex: 'api_key', diff --git a/mcp-auth/frontend/src/pages/Tokens/index.tsx b/mcp-auth/frontend/src/pages/Tokens/index.tsx index 820cf7b..62be88f 100644 --- a/mcp-auth/frontend/src/pages/Tokens/index.tsx +++ b/mcp-auth/frontend/src/pages/Tokens/index.tsx @@ -72,9 +72,14 @@ export default function Tokens() { okType: 'danger', cancelText: '取消', onOk: async () => { - await revokeToken(id, '管理员手动吊销'); - message.success('已吊销'); - load(); + try { + await revokeToken(id, '管理员手动吊销'); + message.success('已吊销'); + } catch (e: any) { + message.error(e?.response?.data?.detail || '吊销失败'); + } finally { + load(); + } }, }); }; @@ -93,9 +98,14 @@ export default function Tokens() { okType: 'danger', cancelText: '取消', onOk: async () => { - await deleteToken(id); - message.success('已删除'); - load(); + try { + await deleteToken(id); + message.success('已删除'); + } catch (e: any) { + message.error(e?.response?.data?.detail || '删除失败'); + } finally { + load(); + } }, }); }; @@ -204,7 +214,7 @@ export default function Tokens() { okText="签发" cancelText="取消" > -
+ - +