C#在 .NET 9.0 中启用二进制序列化:配置、风险与替代方案

在 .NET 9.0 中启用二进制序列化:配置、风险与替代方案

引言

在 .NET 生态中,二进制序列化(Binary Serialization)曾是实现对象持久化和跨进程通信的常用技术。然而,自 .NET 5 起,BinaryFormatter 因安全漏洞被标记为过时,并在默认配置下禁用。对于仍需在 .NET 9.0 中使用此功能的开发者,本文将详细解析启用步骤、潜在风险及推荐替代方案。

一、启用二进制序列化的步骤

修改项目配置

.csproj 文件中添加以下配置,解除 BinaryFormatter 的限制:

xml 复制代码
<PropertyGroup>
  <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>

注意:

此配置会触发编译警告 SYSLIB0011,需开发者显式接受安全风险。

仅建议在完全可控的环境中使用(如内部工具或遗留系统迁移)。

标记可序列化类型

为需要序列化的类添加 [Serializable] 特性:

csharp 复制代码
[Serializable]
public class Person {
public string Name { get; set; }
[NonSerialized] 
public int SecretCode; // 此字段不会被序列化

二、实现序列化与反序列化

序列化对象

csharp 复制代码
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public byte[] Serialize(object obj) 
{
    using (var stream = new MemoryStream()) 
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(stream, obj);
        return stream.ToArray();
    }
}

反序列化对象

csharp 复制代码
public T Deserialize<T>(byte[] data) 
{
    using (var stream = new MemoryStream(data)) 
    {
        var formatter = new BinaryFormatter();
        return (T)formatter.Deserialize(stream);
    }
}

关键问题:

反序列化时需确保目标类型 T 与原始类型完全匹配(包括程序集版本),否则会抛出 SerializationException

三、安全风险与缓解措施

已知风险

反序列化漏洞:攻击者可构造恶意数据触发代码执行(如 ISerializable 接口滥用)。

类型注入:反序列化不受信任数据可能导致意外类型加载。

缓解建议

数据来源可信:仅反序列化来自可信源(如内部系统生成)的数据。

输入验证:对反序列化前的字节流进行签名或校验。

沙箱隔离:在独立 AppDomain 中执行反序列化操作。

四、推荐替代方案

System.Text.Json

特点:高性能、低内存分配,支持异步序列化。

场景:REST API、跨平台数据交换。

csharp 复制代码
var json = JsonSerializer.Serialize(obj);
var obj = JsonSerializer.Deserialize<T>(json);

Protobuf-net

特点:紧凑二进制格式,高效且类型安全。

场景:高性能通信(如 gRPC)、大数据持久化。

csharp 复制代码
using ProtoBuf;
[ProtoContract]
public class Person {
    [ProtoMember(1)]
    public string Name { get; set; }

XML 序列化

特点:可读性强,支持 XML 架构验证。

场景:配置文件、与旧系统兼容。

csharp 复制代码
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, obj);

五、总结

尽管 .NET 9.0 仍支持通过配置启用 BinaryFormatter,但其高安全风险和版本兼容性问题使其不再适用于现代应用。建议优先选择 System.Text.JsonProtobuf-net 等替代方案。若必须使用二进制序列化,请严格遵循以下原则:

仅处理可信数据源。

隔离反序列化操作环境。

监控并更新依赖库以修复潜在漏洞。

技术演进提示:微软已明确表示未来版本可能彻底移除 BinaryFormatter,建议尽早制定迁移计划。

csharp 复制代码
// 历史终将淘汰旧技术,但我们可以优雅地过渡。
pragma warning disable SYSLIB0011

var legacyData = oldFormatter.Deserialize(stream); 
pragma warning restore SYSLIB0011
相关推荐
吴可可1235 小时前
用Teigha修改并保存CAD文件
数据库·算法·c#
西安邮电大学5 小时前
SpringBean完整生命周期
java·spring
刀法如飞5 小时前
DDD 与 Ontology 对比分析:哪一种更适合AI时代复杂系统构建?
java·架构·领域驱动设计
SunnyDays10115 小时前
Java 读写 Excel 公式:从基础到高级的实战总结
java·开发语言·excel
wb043072015 小时前
Java 26
java·开发语言
白露与泡影5 小时前
JVM GC调优实战:从线上频繁Full GC到RT降低80%的全过程
java·开发语言·jvm
范什么特西5 小时前
Spring 动态代理 静态代理
java·后端·spring
醇氧5 小时前
Spring 动态注册 Bean 深度解析:从源码到实践
java·后端·spring
笨拙的老猴子6 小时前
[特殊字符] Java GC机制详解:G1、ZGC、Shenandoah全面解析与版本演进对比
java·开发语言
砍材农夫7 小时前
物联网 基于netty构建mqtt协议规范(遗嘱与保留消息)
java·开发语言·物联网·netty