From 164963b6f765a87fd60a2028d1038470e3c7ebba Mon Sep 17 00:00:00 2001 From: minecraft1024a Date: Sun, 16 Nov 2025 13:31:59 +0800 Subject: [PATCH] =?UTF-8?q?refactor(plugin=5Fsystem):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E7=BA=A7=E8=AE=A4=E8=AF=81=EF=BC=8C=E5=BC=95?= =?UTF-8?q?=E5=85=A5=E7=AB=AF=E7=82=B9=E7=BA=A7=E5=AE=89=E5=85=A8=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前的插件路由认证机制通过在 `RouterInfo` 中设置 `auth_required` 标志,对整个路由组件统一应用API密钥验证。这种方式缺乏灵活性,无法对单个端点进行细粒度的安全控制。 本次重构移除了 `auth_required` 机制,转而引入一个可重用的 FastAPI 依赖项 `VerifiedDep`。插件开发者现在可以按需将其应用到需要保护的特定端点上,从而实现更灵活、更精确的访问控制。 `hello_world_plugin` 已更新,以演示新的认证方式。 BREAKING CHANGE: 移除了 `RouterInfo` 中的 `auth_required` 属性。所有依赖此属性进行认证的插件路由都需要更新,改为在需要保护的端点上使用 `VerifiedDep` 依赖项。 --- plugins/hello_world_plugin/plugin.py | 7 ++++--- src/common/security.py | 7 ++++++- src/plugin_system/base/base_http_component.py | 3 +++ src/plugin_system/base/component_types.py | 2 -- src/plugin_system/core/component_registry.py | 12 ++++-------- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/plugins/hello_world_plugin/plugin.py b/plugins/hello_world_plugin/plugin.py index cb1cfbd9e..5fcfad730 100644 --- a/plugins/hello_world_plugin/plugin.py +++ b/plugins/hello_world_plugin/plugin.py @@ -1,8 +1,8 @@ import random from typing import Any, ClassVar -from mmc.src.plugin_system.base.base_http_component import BaseRouterComponent from src.common.logger import get_logger +from src.common.security import VerifiedDep # 修正导入路径,让Pylance不再抱怨 from src.plugin_system import ( @@ -21,6 +21,7 @@ from src.plugin_system import ( register_plugin, ) from src.plugin_system.base.base_event import HandlerResult +from src.plugin_system.base.base_http_component import BaseRouterComponent from src.plugin_system.base.component_types import InjectionRule, InjectionType logger = get_logger("hello_world_plugin") @@ -208,7 +209,7 @@ class HelloWorldRouter(BaseRouterComponent): def register_endpoints(self) -> None: @self.router.get("/greet", summary="返回一个问候消息") - def greet(): + def greet(_=VerifiedDep): """这个端点返回一个固定的问候语。""" return {"message": "Hello from your new API endpoint!"} @@ -218,7 +219,7 @@ class HelloWorldPlugin(BasePlugin): """一个包含四大核心组件和高级配置功能的入门示例插件。""" plugin_name = "hello_world_plugin" - enable_plugin = True + enable_plugin: bool = True dependencies: ClassVar = [] python_dependencies: ClassVar = [] config_file_name = "config.toml" diff --git a/src/common/security.py b/src/common/security.py index 132d32102..b151dfd09 100644 --- a/src/common/security.py +++ b/src/common/security.py @@ -29,4 +29,9 @@ async def get_api_key(api_key: str = Security(api_key_header_auth)) -> str: status_code=HTTP_403_FORBIDDEN, detail="无效的API密钥", ) - return api_key \ No newline at end of file + return api_key + +# 创建一个可重用的依赖项,供插件开发者在其需要验证的端点上使用 +# 用法: @router.get("/protected_route", dependencies=[VerifiedDep]) +# 或者: async def my_endpoint(_=VerifiedDep): ... +VerifiedDep = Depends(get_api_key) \ No newline at end of file diff --git a/src/plugin_system/base/base_http_component.py b/src/plugin_system/base/base_http_component.py index 218cd4a54..067aca184 100644 --- a/src/plugin_system/base/base_http_component.py +++ b/src/plugin_system/base/base_http_component.py @@ -1,7 +1,10 @@ from abc import ABC, abstractmethod + from fastapi import APIRouter + from .component_types import ComponentType, RouterInfo + class BaseRouterComponent(ABC): """ 用于暴露HTTP端点的组件基类。 diff --git a/src/plugin_system/base/component_types.py b/src/plugin_system/base/component_types.py index 2584608af..d58a5d2e9 100644 --- a/src/plugin_system/base/component_types.py +++ b/src/plugin_system/base/component_types.py @@ -449,8 +449,6 @@ class MaiMessages: class RouterInfo(ComponentInfo): """路由组件信息""" - auth_required: bool = False - def __post_init__(self): super().__post_init__() self.component_type = ComponentType.ROUTER diff --git a/src/plugin_system/core/component_registry.py b/src/plugin_system/core/component_registry.py index 3390cd0a5..ab996fe79 100644 --- a/src/plugin_system/core/component_registry.py +++ b/src/plugin_system/core/component_registry.py @@ -390,7 +390,6 @@ class ComponentRegistry: logger.info("插件HTTP端点功能已禁用,跳过路由注册") return True try: - from src.common.security import get_api_key from src.common.server import get_global_server router_name = router_info.name @@ -408,14 +407,10 @@ class ComponentRegistry: # 5. 生成唯一的URL前缀 prefix = f"/plugins/{plugin_name}" - # 6. 根据需要应用安全依赖项 - dependencies = [] - if router_info.auth_required: - dependencies.append(Depends(get_api_key)) - - # 7. 注册路由,并使用插件名作为API文档的分组标签 + # 6. 注册路由,并使用插件名作为API文档的分组标签 + # 移除了dependencies参数,因为现在由每个端点自行决定是否需要验证 server.app.include_router( - plugin_router, prefix=prefix, tags=[plugin_name], dependencies=dependencies + plugin_router, prefix=prefix, tags=[plugin_name] ) logger.debug(f"成功将插件 '{plugin_name}' 的路由组件 '{router_name}' 挂载到: {prefix}") @@ -880,6 +875,7 @@ class ComponentRegistry: def get_plugin_components(self, plugin_name: str) -> list["ComponentInfo"]: """获取插件的所有组件""" plugin_info = self.get_plugin_info(plugin_name) + logger.info(plugin_info.components) return plugin_info.components if plugin_info else [] def get_plugin_config(self, plugin_name: str) -> dict: