百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

从 .NET 9 开始,运行时将不再提供 BinaryFormatter

yuyutoo 2024-10-18 12:16 2 浏览 0 评论

从 .NET 9 开始,我们不再在运行时中包含 BinaryFormatter 的实现(.NET Framework 保持不变)。API 仍然存在,但无论项目类型是什么,它们的实现始终会抛出异常。因此,设置现有的向下兼容性标志已不足以使用 BinaryFormatter。


在这篇博文中,我将解释为什么做出这一更改以及您可以采取哪些选项。



TL;DR:我该怎么办?

您有两个应对 BinaryFormatter 实现移除的选项:

  1. 迁离 BinaryFormatter。我们强烈建议您考虑停止使用 BinaryFormatter,因为它存在安全风险。BinaryFormatter 迁移指南提供了多种替代方案。

  2. 继续使用 BinaryFormatter。如果您需要在 .NET 9 中继续使用 BinaryFormatter,则需要依赖不受支持的 System.Runtime.Serialization.Formatters NuGet 包,该包恢复了不安全的旧版功能并替换了抛出异常实现。


注意事项

请注意,.NET Framework 不受此更改的影响,并继续包含 BinaryFormatter 的实现。但是,出于同样的原因,我们仍然强烈建议停止使用 .NET Framework 中的 BinaryFormatter。

BinaryFormatter 迁移指南

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/

System.Runtime.Serialization.Formatters

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/compatibility-package



使用 BinaryFormatter 有什么风险?

任何允许输入携带有关要创建对象信息的反序列化器(无论是二进制还是文本),都是一个潜在的安全问题。有一个常见弱点枚举 (CWE) 描述了这个问题:CWE-502“不受信任数据的反序列化”。2002 年 .NET Framework 的初始版本中包含的 BinaryFormatter 就是这样一个反序列化器。我们在 BinaryFormatter 安全指南中也讨论了这一点。

CWE-502“不受信任数据的反序列化”

https://cwe.mitre.org/data/definitions/502.html

BinaryFormatter 安全指南

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide



我们为什么要移除 BinaryFormatter

我们坚信 .NET 应该让客户能够轻松地做正确的事情,并尽量避免或杜绝错误的操作。我们通常将此称为“成功的陷阱”。

发布一种被广泛认为是不安全的技术与这一目标背道而驰。与此同时,我们也有责任确保客户能够支持并推进他们现有代码的发展。我们不能只是简单地从 .NET 版本中删除广泛使用的组件,即使提前很久就进行了通知。我们还需要一个迁移计划和临时解决方案。

这次移除并非突然发生。由于我们已经知道使用 BinaryFormatter 时,会存在风险,所以我们将其从 .NET Core 1.0 中排除。但因为缺乏明确的迁移路径来使用更安全的替代方案,并且客户依旧存在需求,我们在 .NET Core 2.0 中重新引入了 BinaryFormatter 。

从那时起,我们就一直在努力移除 BinaryFormatter,在多种项目类型中慢慢将其默认禁用,但如果使用者仍然需要向下兼容,则允许他们通过可选标记使用:

  • 2020:BinaryFormatter 淘汰计划

    https://github.com/dotnet/designs/blob/main/accepted/2020/better-obsoletion/binaryformatter-obsoletion.md

  • 2023:.NET 8 更新:默认情况下实现会抛出异常

    https://github.com/dotnet/announcements/issues/284

  • 2024:.NET 9 更新:在发布周期早期宣布移除意图

    https://github.com/dotnet/announcements/issues/293

  • 2024:.NET 9 更新:移除已完成

    https://github.com/dotnet/announcements/issues/317

  • 2024:.NET 9 重大变更:内置 BinaryFormatter 实现被移除,且始终会抛出异常

    https://learn.microsoft.com/en-us/dotnet/core/compatibility/serialization/9.0/binaryformatter-removal


在 .NET 9 中,我们移除了 BinaryFormatter 上所有剩余的内置依赖项,并用一个始终抛出异常的实现替换了它。



前进的方向

新代码不应该依赖于BinaryFormatter。对于现有代码,您应该首先研究 BinaryFormatter 的替代方案。如果您不控制序列化程序而只执行反序列化,则可以考虑只读取 BinaryFormatter 有效负载,而不执行任何反序列化。如果以上方法均不适用于您,您可以通过依赖(不受支持的)兼容包来恢复实现。

我将在下文中详细探讨这些选项。

兼容包

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/compatibility-package



迁移替代

首先,您应该调查是否可以用其他序列化程序替换 BinaryFormatter。我们有四条建议:

  • 基于文本的序列化。如果不需要二进制序列化格式,您可以考虑使用 JSON 或 XML 序列化格式。这些序列化器包含在 .NET 中,并由我们支持。

    o 使用 System.Text.Json 进行 JSON 序列化

    https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/migrate-to-system-text-json

    o 使用 System.Runtime.Serialization.DataContractSerializer 进行 XML 序列化

    https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/migrate-to-datacontractserializer

  • 基于二进制的序列化 如果您的场景需要紧凑的二进制表示形式,则建议使用以下序列化格式和开源序列化器:

    o使用 MessagePack for C# 进行 MessagePack 序列化

    https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/migrate-to-messagepack

    o使用 protobuf-net 进行 Protocol Buffers 序列化

    https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/migrate-to-protobuf-net

由于 DataContractSerializer 遵循与 BinaryFormatter 相同的属性和接口(即 [Serializable] 和 ISerializable),因此它可能是最容易迁移的。如果您的迁移目标是采用现代、高性能的序列化器,或需要更好的跨平台兼容性,其他选项也值得考虑。



读取 BinaryFormatter 的数据

如果您的代码不控制序列化而只控制反序列化,请使用新的 NrbfDecoder读取 BinaryFormatter 的数据。这允许您在没有任何反序列化的情况下读取编码数据。这相当于使用不带反序列化的 JSON/XML 读取器:

using System.Formats.Nrbf;
void Read(Stream payload){ SerializationRecord rootObject = NrbfDecoder.Decode(payload);
if (rootObject is PrimitiveTypeRecord primitiveRecord) { Console.WriteLine($"It was a primitive value: '{primitiveRecord.Value}'"); } else if (rootObject is ClassRecord classRecord) { Console.WriteLine($"It was a class record of '{classRecord.TypeName.AssemblyQualifiedName}' type name."); } else if (rootObject is SZArrayRecord<byte> arrayOfBytes) { Console.WriteLine($"It was an array of `{arrayOfBytes.Length}`-many bytes."); }}


有关更多详细信息,请查看 Nrbf 文档

NrbfDecoder

https://learn.microsoft.com/en-us/dotnet/api/system.formats.nrbf.nrbfdecoder?view=net-8.0

数据

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/read-nrbf-payloads

Nrbf 文档

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/read-nrbf-payloads



BinaryFormatter 兼容包

如果您已经探索过这些选项并确定无法迁离 BinaryFormatter,那么您还可以安装不受支持的 System.Runtime.Serialization.Formatters NuGet 包并将兼容性开关设置为 true:

<PropertyGroup> <TargetFramework>net9.0</TargetFramework> <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization></PropertyGroup>
<ItemGroup> <PackageReference Include="System.Runtime.Serialization.Formatters" Version="9.0.0" /></ItemGroup>


该包将 BinaryFormatter 的内置实现替换为可正常运行的实现,同时也带回了漏洞和风险。如果您迫不及待地想要迁移到 .NET 9,并且尚未替换 BinaryFormatter,那么它可作为临时解决方案。


由于 BinaryFormatter API 仍然存在,并且此包仅替换了内置实现,因此您只需从应用程序项目中引用它即可。针对 BinaryFormatter 编译的现有代码将继续工作。


注意事项

该兼容包不受支持且不安全。我们强烈建议不要依赖此包,而是尽快迁移离开 BinaryFormatter。

System.Runtime.Serialization.Formatters

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/compatibility-package



总结

自 .NET Core 发布以来,我们一直在逐步淘汰 BinaryFormatter,因为它存在安全风险


从 .NET 9 开始,我们不再在运行时中提供该实现。我们建议您从 BinaryFormatter 迁离。如果您无法做到这一点,您可以尝试在不进行反序列化的情况下读取二进制有效负载,或者您可以依赖于不受支持的兼容性包

它存在安全风险

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

从 BinaryFormatter 迁离

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/

在不进行反序列化的情况下读取二进制有效负载

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/read-nrbf-payloads

不受支持的兼容性包

https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-migration-guide/compatibility-package



相关推荐

史上最全的浏览器兼容性问题和解决方案

微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...

平面设计基础知识_平面设计基础知识实验收获与总结
平面设计基础知识_平面设计基础知识实验收获与总结

CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...

2025-02-21 16:01 yuyutoo

写作排版简单三步就行-工具篇_作文排版模板

和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...

写一个2048的游戏_2048小游戏功能实现

1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...

今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……

  最近的天气暖和得让很多小伙伴们喊“热”!!!  昨天的气温到底升得有多高呢?你家有没有榜上有名?...

CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式

之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...

柠檬科技肖勃飞:大数据风控助力信用社会建设

...

你的自我界限够强大吗?_你的自我界限够强大吗英文

我的结果:A、该设立新的界限...

行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?

行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...

让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华

去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...

2025-02-21 16:00 yuyutoo

今年国家综合性消防救援队伍计划招录消防员15000名

记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...

一起盘点最新 Chrome v133 的5大主流特性 ?

1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...

竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使

style="text-align:center;"data-mce-style="text-align:...

学物理能做什么?_学物理能做什么 卢昌海

作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...

你不知道的关于这只眯眼兔的6个小秘密
你不知道的关于这只眯眼兔的6个小秘密

在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...

2025-02-21 16:00 yuyutoo

取消回复欢迎 发表评论: