在 .NET 9.0 中啟用二進制序列化:配置、風險與替代方案
- 引言
- 一、啟用二進制序列化的步驟
- 二、實現序列化與反序列化
- 三、安全風險與緩解措施
- 四、推薦替代方案
- 五、總結
引言
在 .NET 生態中,二進制序列化(Binary Serialization)曾是實現對象持久化和跨進程通信的常用技術。然而,自 .NET 5 起,BinaryFormatter
因安全漏洞被標記為過時,并在默認配置下禁用。對于仍需在 .NET 9.0 中使用此功能的開發者,本文將詳細解析啟用步驟、潛在風險及推薦替代方案。
一、啟用二進制序列化的步驟
修改項目配置
在 .csproj
文件中添加以下配置,解除 BinaryFormatter
的限制:
<PropertyGroup><EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
</PropertyGroup>
注意:
此配置會觸發編譯警告 SYSLIB0011
,需開發者顯式接受安全風險。
僅建議在完全可控的環境中使用(如內部工具或遺留系統遷移)。
標記可序列化類型
為需要序列化的類添加 [Serializable]
特性:
[Serializable]
public class Person {
public string Name { get; set; }
[NonSerialized]
public int SecretCode; // 此字段不會被序列化
二、實現序列化與反序列化
序列化對象
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();}
}
反序列化對象
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、跨平臺數據交換。
var json = JsonSerializer.Serialize(obj);
var obj = JsonSerializer.Deserialize<T>(json);
Protobuf-net
特點:緊湊二進制格式,高效且類型安全。
場景:高性能通信(如 gRPC)、大數據持久化。
using ProtoBuf;
[ProtoContract]
public class Person {[ProtoMember(1)]public string Name { get; set; }
XML 序列化
特點:可讀性強,支持 XML 架構驗證。
場景:配置文件、與舊系統兼容。
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stream, obj);
五、總結
盡管 .NET 9.0 仍支持通過配置啟用 BinaryFormatter
,但其高安全風險和版本兼容性問題使其不再適用于現代應用。建議優先選擇 System.Text.Json
或 Protobuf-net
等替代方案。若必須使用二進制序列化,請嚴格遵循以下原則:
僅處理可信數據源。
隔離反序列化操作環境。
監控并更新依賴庫以修復潛在漏洞。
技術演進提示:微軟已明確表示未來版本可能徹底移除 BinaryFormatter
,建議盡早制定遷移計劃。
// 歷史終將淘汰舊技術,但我們可以優雅地過渡。
pragma warning disable SYSLIB0011var legacyData = oldFormatter.Deserialize(stream);
pragma warning restore SYSLIB0011