第二阶段已完成:统一插件平台已从“内置功能开关”扩展为可安装、签名校验、版本激活和回滚的插件系统。
主要成果:
- 新增独立插件 SDK:[PluginContracts.cs (line 11)](E:/jiaowu/src/Jiaowu.Plugin.Abstractions/PluginContracts.cs:11)
- 支持 RSA-PSS/SHA-256 签名插件包、Host API 兼容性和 ZIP 安全检查:[PluginPackageValidator.cs (line 14)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/Plugins/PluginPackageValidator.cs:14)
- 支持暂存、待激活、重启装载、失败记录、版本回滚:[PluginPackageService.cs (line 32)](E:/jiaowu/src/Jiaowu.Api/Infrastructure/Plugins/PluginPackageService.cs:32)
- 插件可注册控制器、服务、数据库迁移、后台任务和事件处理器
- 外部插件 API 统一使用 /api/plugin-extensions/{pluginId},并受启用状态中间件控制
- 插件中心新增 ZIP/SIG 上传、状态展示、激活、回滚和删除功能:[PluginsView.vue (line 212)](E:/jiaowu/web/src/views/PluginsView.vue:212)
- 提供可运行示例插件:[SamplePlugin.cs (line 10)](E:/jiaowu/samples/Jiaowu.SamplePlugin/SamplePlugin.cs:10)
- 提供打包签名脚本:[package-plugin.ps1](E:/jiaowu/scripts/package-plugin.ps1)
- 完整开发文档:[plugin-sdk.md (line 1)](E:/jiaowu/docs/plugin-sdk.md:1)
- 系统版本已调整为 3.0.0-beta1
This commit is contained in:
1 parent
7e3f138875
commit
05683e502a
35 files changed
+11247
-24
No files matched your search
@@ -0,0 +1,92 @@
|
||||
# 明序插件 SDK
|
||||
|
||||
统一插件平台只装载经过受信任发布者 RSA 签名的后端插件。上传、激活和运行是三个独立阶段:上传后先暂存;管理员标记某个版本为待激活;服务重启时再次验证签名并装载,成功后才成为活动版本。
|
||||
|
||||
## 创建插件
|
||||
|
||||
插件项目面向 `net10.0`,引用 `src/Jiaowu.Plugin.Abstractions`。可以从 `samples/Jiaowu.SamplePlugin` 复制起步。入口类型必须实现 `IJiaowuPluginModule`:
|
||||
|
||||
```csharp
|
||||
public sealed class MyPluginModule : IJiaowuPluginModule
|
||||
{
|
||||
public void ConfigureServices(
|
||||
IServiceCollection services,
|
||||
IConfiguration configuration)
|
||||
{
|
||||
services.AddScoped<MyPluginService>();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
插件控制器必须使用 `/api/plugin-extensions/{pluginId}` 前缀,并自行声明 `[Authorize]`、角色和数据范围校验。插件开关只决定扩展是否开放,不能替代业务授权。
|
||||
|
||||
## plugin.json
|
||||
|
||||
包根目录必须包含 `plugin.json`,后端程序集放在 `backend/`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "school.example",
|
||||
"name": "学校示例插件",
|
||||
"description": "插件用途说明",
|
||||
"version": "1.0.0",
|
||||
"publisherId": "school-it",
|
||||
"hostApiVersion": "1",
|
||||
"category": "扩展插件",
|
||||
"backendAssembly": "backend/School.Example.dll",
|
||||
"moduleType": "School.Example.ExamplePluginModule",
|
||||
"capabilities": ["example.read"]
|
||||
}
|
||||
```
|
||||
|
||||
插件 ID 和版本一旦发布不能原地覆盖。升级必须使用新的语义版本。
|
||||
|
||||
## 数据迁移、事件和后台任务
|
||||
|
||||
- 实现 `IPluginDatabaseMigration` 声明 SQLite/MySQL 迁移语句。每个迁移以 `(PluginId, MigrationId)` 唯一记录,并在事务中只执行一次。
|
||||
- 实现 `IPluginBackgroundTask` 注册定时任务。宿主强制最短 30 秒间隔,并隔离记录任务异常。
|
||||
- 通过 `IPluginEventHandler<TEvent>` 订阅事件,使用 `AddPluginEventHandler<TEvent, THandler>()` 注册;通过 `IPluginEventPublisher` 发布事件。
|
||||
|
||||
迁移只应操作本插件拥有的表。不要修改 Identity、成绩、学籍等核心表,也不要在迁移中删除业务数据。
|
||||
|
||||
## 发布者密钥
|
||||
|
||||
私钥只保存在发布流水线或密钥管理系统,服务器只部署公钥。示例生成命令:
|
||||
|
||||
```powershell
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out school-it-private.pem
|
||||
openssl rsa -pubout -in school-it-private.pem -out school-it-public.pem
|
||||
```
|
||||
|
||||
生产配置:
|
||||
|
||||
```dotenv
|
||||
Plugins__StoragePath=/var/lib/jiaowu/plugins
|
||||
Plugins__TrustedPublishers__0__Id=school-it
|
||||
Plugins__TrustedPublishers__0__PublicKeyPath=/etc/jiaowu/plugin-publishers/school-it-public.pem
|
||||
```
|
||||
|
||||
服务账号需要读取公钥、读写插件存储目录;其他普通账号不应具有写权限。
|
||||
|
||||
## 打包与签名
|
||||
|
||||
仓库脚本会执行 Release 发布、生成 ZIP,并使用 RSA-PSS/SHA-256 生成分离签名:
|
||||
|
||||
```powershell
|
||||
./scripts/package-plugin.ps1 `
|
||||
-Project samples/Jiaowu.SamplePlugin/Jiaowu.SamplePlugin.csproj `
|
||||
-Manifest samples/Jiaowu.SamplePlugin/plugin.json `
|
||||
-PrivateKey C:/secure/school-it-private.pem
|
||||
```
|
||||
|
||||
产物位于 `.artifacts/plugins`。把 `.zip` 和同名 `.sig` 一起上传到插件中心。
|
||||
|
||||
## 激活、升级与回滚
|
||||
|
||||
1. 先执行宿主数据库迁移并启动包含插件平台的服务版本。
|
||||
2. 在插件中心上传 ZIP 和 SIG;签名、路径、大小、清单和 Host API 必须全部通过。
|
||||
3. 点击“激活”,版本进入“待重启激活”。
|
||||
4. 按维护流程重启服务;宿主重新验证包、装载模块并运行插件迁移。
|
||||
5. 若新版本异常,在插件中心对历史版本点击“回滚到此版本”,然后再次重启。
|
||||
|
||||
插件程序集在独立加载上下文中运行,但仍属于受信任的服务器代码。只应信任经过代码审查的发布者;面向不受信任第三方的插件必须使用后续的独立进程/远程服务模式。
|
||||
Reference in new issue
Block a user