Elsa Workflow JSON 类型加固:SerializationTypeRegistry 数据模型与信任边界解析

发布时间:2026/10/4 9:47:23
Elsa Workflow JSON 类型加固:SerializationTypeRegistry 数据模型与信任边界解析 后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载导读本文围绕 ElsaThe Workflow Engine for .NET的 Workflow JSON 类型加固Workflow JSON Type Hardening特性深入讲解其核心数据模型——SerializationTypeOptions、SerializationTypeRegistry与 Workflow Type Identifier别名 / 遗留名称机制。通过本文读者将理解为什么 Elsa 需要一套独立于表达式配置的专用序列化类型注册表内置默认别名覆盖了哪些类型模块与扩展如何显式注册可序列化类型与兼容性遗留名称以及这一信任模型如何同时保证「旧工作流 JSON 可继续加载」与「未知/危险类型一律拒绝」两大目标。本文内容以仓库 specs/010-workflow-json-hardening/ 下的设计文档data-model.md、spec.md、contracts/、research.md、plan.md、quickstart.md、tasks.md为主体并以 src/modules/Elsa.Common/Serialization/ 等源码实现作为佐证。一、设计动机为什么需要专用数据模型1.1 问题背景工作流定义、工作流状态、触发器Trigger/书签Bookmark载荷等 JSON 中经常需要以字符串形式序列化 CLR 类型标识Type Identifier。早期实现把类型解析的信任边界建立在ExpressionOptions之上由此带来两个问题信任边界混淆表达式别名本用于表达式求值与设计器变量元数据却被工作流 JSON 复用为反序列化类型依据任意类型加载风险若允许直接用Type.GetType按字符串加载恶意或损坏的 JSON 可以诱导加载任意 CLR 类型构成反序列化安全隐患。GitHub issue #7541 明确提出要用**专用别名设计dedicated alias design**重构这一机制。参见 spec.md 的输入说明。1.2 核心设计决策research.md 记录了三个关键决策决策内容被否决的替代方案专用工作流 JSON 注册表使用 workflow-specific 注册表与 Options 对象统一服务于TypeJsonConverter、PolymorphicObjectConverter、工作流状态序列化、书签载荷序列化、Trigger 比较、哈希与描述符契约复用IWellKnownTypeRegistry由ExpressionOptions喂养Type.GetType直接回退显式遗留兼容名称兼容读仅接受注册过的别名与遗留名称含已注册类型的简单程序集限定名、完整程序集限定名、以及封闭在已注册元素类型之上的受支持集合包装宽泛的程序集白名单难以推理可能意外暴露信任程序集中的无关类型别名优先的公共描述符契约Incident Strategy 描述符输出工作流 JSON 别名兼容窗口期内保留遗留 CLR 名称可读描述符继续输出 CLR 名称延续不一致契约注意这些内容属于仓库内的设计文档与实现证据非营销性描述。二、数据模型总览data-model.md 定义了三个核心构件下面逐一展开。2.1 SerializationTypeOptions —— 类型标识的静态声明职责存储「工作流 JSON 别名 → 具体类型」的映射存储「可选遗留名称 → 同一具体类型」的映射提供工作流载荷所需的默认原始类型primitive别名与JSON 岛JSON island别名位于Elsa.Common使非工作流序列化层也能共享同一信任边界。源码位于 src/modules/Elsa.Common/Serialization/SerializationTypeOptions.cs。其内部维护两个字典AliasTypeDictionary只读暴露以标识符为键指向类型同时容纳别名与遗留名称TypeAliasDictionary只读暴露以类型为键指向首选别名用于写 JSON 时输出。构造函数内置了以下默认注册见SerializationTypeOptions构造器#L20-L50类型首选别名备注shortInt16原始类型intInt32原始类型longInt64原始类型并注册遗留名称LongfloatSingle原始类型objectObjectstringStringboolBooleandecimalDecimaldoubleDoublebyte[]ByteArray数组形态GuidGuidDateTimeDateTimeDateTimeOffsetDateTimeOffsetTimeSpanTimeSpanStreamStreamExpandoObjectJSONJSON 岛JsonElementJsonElementJSON 岛JsonNodeJsonNodeJSON 岛JsonObjectJsonObjectJSON 岛JsonArrayJsonArrayJSON 岛IDictionarystring,stringStringDictionary集合包装IDictionarystring,objectObjectDictionary集合包装Dictionarystring,stringStringMap集合包装Dictionarystring,objectObjectMap集合包装三个注册方法#L65-L84构成了扩展的基础public SerializationTypeOptions RegisterTypeAlias(Type type, string alias); // 首选别名可写可读 public SerializationTypeOptions RegisterLegacyTypeName(Type type, string typeName); // 遗留名称仅读 public SerializationTypeOptions RegisterLegacySimpleAssemblyQualifiedName(Type type); // 注册当前简单程序集限定名配套的 Fluent 扩展位于 src/modules/Elsa.Common/Extensions/SerializationTypeOptionsExtensions.cs常用 API 包括AddTypeAliasT(string alias)/AddTypeAliasT()注册首选别名后者直接用typeof(T).NameAddTypeAliasWithLegacyNameT(string alias)同时注册首选别名与当前简单程序集限定名兼容性窗口期的标准姿势AddLegacySimpleAssemblyQualifiedNameT()仅注册兼容性遗留名称AddSimpleAssemblyQualifiedTypeAlias(Type)对纯兼容类型把简单程序集限定名直接作为首选别名。2.2 SerializationTypeRegistry —— 运行时注册表职责由SerializationTypeOptions构建的运行时注册表将别名与已注册遗留名称解析为类型列出全部已注册类型供兼容性解析使用返回用于写新工作流 JSON 与公共描述符值的首选别名。接口定义于 src/modules/Elsa.Common/Serialization/ISerializationTypeRegistry.cs实现位于 src/modules/Elsa.Common/Serialization/SerializationTypeRegistry.cspublic interface ISerializationTypeRegistry { void RegisterType(Type type, string alias); // 注册类型别名 bool TryGetAlias(Type type, out string alias); // 类型 - 首选别名 bool TryGetType(string alias, out Type type); // 别名/遗留名 - 类型 IEnumerableType ListTypes(); // 列出全部已注册类型 }值得注意的细节SerializationTypeRegistry在注册值类型别名时会自动派生可空类型标识——当type.IsPrimitive或「值类型且非可空」时会额外登记{alias}?→NullableT并在已存在首选别名时登记NullableT→{alias}?#L51-L58。这意味着Int32?、DateTime?这类标识可以直接读写无需手动注册。SerializationTypeRegistry.CreateDefault()静态工厂直接用默认SerializationTypeOptions构建注册表供无 DI 场景使用。2.3 Workflow Type Identifier —— 两类标识符按>options.AddTypeAliasExceptionState(nameof(ExceptionState)); options.AddTypeAliasFaultException(nameof(FaultException)); options.AddTypeAliasVariablesDictionary(nameof(VariablesDictionary)); options.AddTypeAliasToken(nameof(Token)); options.AddTypeAliasWithLegacyNameFlowJoinMode(nameof(FlowJoinMode)); options.AddTypeAliasWithLegacyNameWorkflowStorageDriver(nameof(WorkflowStorageDriver)); options.AddTypeAliasWithLegacyNameFaultStrategy(nameof(FaultStrategy)); options.AddTypeAliasWithLegacyNameContinueWithIncidentsStrategy(nameof(ContinueWithIncidentsStrategy)); // …… 常见异常类型、JObject/JArray 等注意FlowJoinMode还显式注册了一个旧版完整 CLR 名称Elsa.Workflows.Core.Activities.Flowchart.Models.FlowJoinMode, Elsa.Workflows.Core作为遗留标识演示了「迁移/重命名后仍可读旧 JSON」的场景。AddTypeAliasWithLegacyName恰好对应>dotnet test test/unit/Elsa.Workflows.Core.UnitTests/Elsa.Workflows.Core.UnitTests.csproj --filter SerializationTypeResolverTests dotnet test test/unit/Elsa.Workflows.Runtime.UnitTests/Elsa.Workflows.Runtime.UnitTests.csproj --filter WorkflowRuntimeFeatureTests对应测试文件与关注点见 tasks.mdSerializationTypeResolverTests.csT009/T010验证专用注册表兼容性、表达式专属别名不被工作流 JSON 接受ListTests.csT013Incident Strategy 描述符回归测试WorkflowRuntimeFeatureTests.csT017与 WorkflowTriggerEqualityComparerTests.csT018运行时载荷注册与触发器比较器。计划中的实施策略tasks.md 末尾依次为建立专用注册表并切换转换器 → 保留既有 JSON 兼容性 → 对齐 Incident Strategy API 描述符 → 将运行时/模块载荷注册迁出表达式选项 → 目标测试与文档验证。八、模块作者与扩展开发者指南作为模块或扩展作者若要让你序列化的类型进入工作流 JSON 信任边界标准姿势是在模块的 Feature 中services.ConfigureSerializationTypeOptions(options ...)对需要写入新 JSON 的类型使用options.AddTypeAliasT(别名)或AddTypeAliasWithLegacyNameT(别名)对仅需兼容旧数据的类型使用options.AddLegacySimpleAssemblyQualifiedNameT()如果类型同时用于表达式求值请同时保留表达式侧配置——二者是两条独立的信任边界FR-001/FR-003。若类型未注册写入时会输出UnregisteredClrType:前缀的元数据别名读取时反序列化为Exception从而既不丢信息、也不冒险加载TypeJsonConverter#L44-L55。结语Workflow JSON 类型加固的数据模型以「别名写、注册表读、遗留名称兼容、未知即拒绝」为纲SerializationTypeOptions负责静态声明默认与扩展注册SerializationTypeRegistry负责运行时解析与反向取别名SerializationTypeResolver在解析器层面把信任边界收敛为「注册表 受控集合包装 已注册程序集」TypeJsonConverter与PolymorphicObjectConverter统一消费该注册表。这一模型既让 Elsa 的公共 API如 Incident Strategy 描述符与工作流 JSON 读写契约保持一致也为模块作者提供了明确、可扩展、可验证的序列化信任登记机制。相关配套文档可继续查阅 spec.md、research.md 与 contracts/workflow-json-type-identifiers.md。赞分享后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载相关推荐Apache Airflow 安全模型全解用户类型、信任边界与部署隔离加固指南Apache Airflow 安全模型全解用户类型、信任边界与部署隔离加固指南 Apache Airflow 的安全模型围绕谁拥有哪种信任级别展开部署管后端任务调度工作流自动化数据编排批处理数据工程流程编排Apache APISIX 威胁模型解析攻击面、信任边界与安全加固实践Apache APISIX 威胁模型解析攻击面、信任边界与安全加固实践 本文以 Apache APISIX 官方威胁模型根目录 THREAT_MODEL.mAPI网关后端云原生微服务LunaTranslator 视觉小说实时翻译完整指南从第一次运行到进阶调优LunaTranslator 视觉小说实时翻译完整指南从第一次运行到进阶调优 LunaTranslator 是一款免费开源的视觉小说实时翻译工具它从正在运行桌面应用OCR人工智能上一篇Ghostfolio PWA清单文件现代化财富管理的渐进式Web应用实现下一篇LokiJS事件驱动编程终极指南掌握LokiEventEmitter的完整使用技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考