将对象序列化为文件时的C#最佳实践

时间:2010-12-17 23:03:18

标签: c# serialization

我正在构建一个小应用程序,需要将对象保存到文件中以保存用户数据。 关于我对此文件的序列化,我有两个问题:

  1. 我正在创建的对象有一些公共属性和一个事件。我将[Serializable]属性添加到我的对象中,然后意识到我无法序列化包含事件的对象。 然后我发现我可以在事件[field:NonSerialized]之上添加一个属性,它会起作用。这是最好的方法吗,或者我应该尝试构建我的Serializable对象而不发生任何事件?

  2. 我正在序列化的对象保存了一些有关该应用的用户设置。这些设置不够灵敏,无法在文件中加密它们,但我仍然不希望它们在不打开我的应用程序的情况下手动篡改。当我使用普通BinaryFormatter对象将我的对象序列化为文件时,通过Serialize()方法,我在文件中看到.net对象类型的可读名称,我将其保存到。有没有办法让某人对此进行逆向工程,看看在不使用我的程序的情况下保存了什么?有没有办法让某人建立一个小应用程序,并找出如何DeSerialize此文件中的信息?如果是这样,我将如何隐藏此文件中的信息?

  3. 在这种情况下将对象序列化为文件时,是否还有其他提示/建议/最佳实践?

    提前致谢!

3 个答案:

答案 0 :(得分:11)

如果您的对象实现了ISerializable接口,您可以自己控制所有存储/序列化的数据,并且可以控制反序列化。

如果您的项目及时发展,这一点非常重要。因为您可能会删除某些属性,添加其他属性或更改行为。

我总是在序列化包中添加一个版本。这样我知道对象存储时的版本是什么,因此我知道如何对其进行反序列化。

[Serializable]
class Example : ISerializable {
   private static const int VERSION = 3;

   public Example(SerializationInfo info, StreamingContext context) {
      var version = info.GetInt32("Example_Version", VERSION);
      if (version == 0) {
         // Restore properties for version 0
      }
      if (version == 1) {
         // ....
      }
   }

   void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
       info.AddValue("Example_Version", VERSION);
       // Your data here
   }

}

如果您不加密,则可以非常轻松地“读取”您的数据。很容易意味着您可能需要投入几个小时。如果您存储的数据值几天,这意味着它很容易,如果它只值几分钟很难。如果你明白这一点。

加密数据的一种非常简单的方法是通过ProtectedData类使用Windows DPAPI。

答案 1 :(得分:3)

1:使用BinaryFormatter,是的 - 您需要NonSerialized用于事件(除非您实现了ISerializable,但这增加了很多工作);然而,我几乎记录在案,我不会在这里使用BinaryFormatter。对您的类型进行一系列更改并不是非常原谅。我会使用与代码内部相关的东西; XmlSerializer的; DataContractSerializer,JavaScriptSerializer。我也可以建议二元替代品; NetDataContractSerializer,protobuf-net(我自己的)等等。

2:是的,几乎所有不涉及正确加密的实现,如果有人关心他们可以进行逆向工程并获得字符串。所以它取决于它需要隐藏的程度。简单地通过GZipStream运行现有的序列化可能足以满足您的需求,但这只是一个反对随意检查的掩码。它不会阻止任何人有理由寻找数据。

如果数据需要是安全的,那么您需要使用用户在应用启动时输入的密钥进行适当的加密,或者根据用户资料安全地存储证书等。

答案 2 :(得分:0)

  1. 我会从对象中删除事件。这样有点干净。

  2. 任何东西都可以逆向工程。只需在保存文件时加密即可。这很容易做到。当然,加密密钥必须存储在应用程序的某个地方,因此,除非您对代码进行模糊处理,否则确定的黑客将能够访问它。