c# - 自定义 JSON 转换器,以帮助反序列化回确切原始类型的对象
问题描述
我正在做的事情已经Json.net
通过设置TypeNameHandling
来实现TypeNameHandling.Objects
。这样对象类型也将被序列化,并且反序列化的对象将具有确切的原始类型。
但是 usingTypeNameHandling
暴露了一些安全问题,并要求我们使用自定义SerializationBinder
来限制将支持哪些类型以避免可能的代码注入。这不是我试图寻找另一种解决方案的主要原因。实际上我发现通过使用TypeNameHandling.Objects
,一个对象将被序列化为一个复杂的 JSON,不仅包括对象数据本身和对象类型,还包括其他一些对我来说看起来多余的属性。
我认为我们只需要一个包含有关对象类型信息的属性(例如对象类型的程序集限定名称),所以我想创建一个自定义JsonConverter
,它将任何对象序列化为一些 JSON,如下所示:
{
"Item" : "normal JSON string of object",
"ItemType" : "assembly qualified name of object type"
}
这还不够吗?正如我之前所说,除了 2 个类似于那些(具有不同名称)的属性外,Json.net
lib 还包括一些其他属性(签名...),这对我来说真的是多余的。
我不是在问如何实现JsonConverter
我上面提到的自定义。我只是想知道该转换器(具有简化的 JSON 结构)是否可以,或者我应该使用Json.net
with提供的标准解决方案TypeNameHandling
(涉及更复杂的 JSON 结构)?我主要担心的是由于要转换/序列化/传输更多数据而导致TypeNameHandling
设置为可能的性能问题。Objects
标准解决方案的另一个问题是性能问题,实际上我只需要将自定义转换逻辑应用于确切类型的所有对象object
,而不是所有其他强类型对象(可能仍然不必要地应用TypeNameHandling
?)
解决方案
我对您提出的多态自定义设计有一些反应JsonConverter
(我们称其为基本类型):PolymorphicConverter<T>
T
关于安全,你写道,
... using
TypeNameHandling
暴露了一些安全问题,并要求我们使用自定义SerializationBinder
来限制将支持哪些类型以避免可能的代码注入。可能出现的相同安全风险也
TypeNameHandling
将出现在PolymorphicConverter<T>
.这里的风险是攻击者欺骗一些多态反序列化代码来实例化攻击小工具。由于 Json.Net TypeNameHandling auto,请参阅Newtonsoft Json和External json 中的 TypeNameHandling 警告?示例和讨论。如果攻击者使用转换器支持的属性中指定的攻击小工具类型制作 JSON ,那么它最终可能会实例化攻击小工具并实施攻击。
"ItemType"
PolymorphicConverter<T>
您可以通过仅对那些在实践中实际上是多态的属性应用(或[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
就此而言)启用对已知多态属性或数组项的多态反序列化的支持来减少攻击面——但如果这些属性的多态基类型只是碰巧与攻击小工具兼容,您将容易受到攻击。因此,无论使用什么机制,您仍然需要像自定义这样的东西
SerializationBinder
来过滤掉顽皮的类型,无论您如何在 JSON 中编码类型信息的细节。JSON 文件大小。Json.NET 通过在对象的开头添加一个属性来编码类型信息:
"$type" : "assembly qualified name of object type"
您的计划是改为添加:
"ItemType" : "assembly qualified name of object type"
目前尚不清楚为什么会有优势,除非您的类型名称更紧凑。
表现。你写了,
我主要担心的是由于要转换/序列化/传输更多数据而导致
TypeNameHandling
设置为可能的性能问题。Objects
首先,为什么不只是测量和找出?见https://ericlippert.com/2012/12/17/performance-rant/
其次,Newtonsoft 有一个设置
MetadataPropertyHandling
,当设置为 时Default
,假定多态属性"$type"
在每个对象中排在首位,因此能够将它们流式传输,而无需将整个 JSON 预加载到JToken
层次结构中。如果您的转换器无条件地预加载到
JToken
层次结构中以获取"ItemType"
属性值,则它的性能可能会更差。关于将多态反序列化限制为仅需要的属性,您写道:
标准解决方案的另一个问题是性能问题,实际上我只需要将自定义转换逻辑应用于确切类型的所有对象
object
,而不是所有其他强类型对象无论哪种方式,这都可以通过自定义
ContractResolver
. 根据您选择的解决方案,覆盖DefaultContractResolver.CreateProperty
和,何时JsonProperty.PropertyType == typeof(object)
,设置TypeNameHandling
或根据需要。Converter
推荐阅读
- c# - 尝试激活 yyy 时无法解析类型 xxx 的服务
- php - 如何将登录信息存储在关联数组中
- android - 新的 TabLayout 材质组件如何设置 Tab 背景颜色
- oracle - 在 Oracle sqldeveloper 中为 Schema 启用 ORDS
- html - 更改 td 的宽度
- java - 自带jar文件
- react-native - React Native - Native Base - 显示错误
- c - 使用 fgetc 读取文件会提供额外的(垃圾)值
- php - 使用 php/javascript 在纬度/经度点数组中查找多边形/线/点
- reactjs - 如何知道一个函数是否在 redux thunk dispatch 中被调用?