Лучшая практика С# при сериализации объектов в файл
Я создаю небольшое приложение, которое должно сохранить объект в файле, чтобы сохранить пользовательские данные.
У меня есть два вопроса о моей сериализации в этот файл:
-
Объект, который я создаю, имеет некоторые общедоступные свойства и событие. Я добавил атрибут [Serializable]
к моему объекту, а затем понял, что не могу сериализовать объект с событием в нем.
Затем я обнаружил, что могу добавить атрибут выше моего события [field:NonSerialized]
, и он будет работать. Это лучший способ сделать это, или я должен попытаться построить мои объекты Serializable без каких-либо событий внутри?
-
Объект, который я сериализую, сохраняет некоторые настройки пользователя в приложении. Эти настройки недостаточно чувствительны, чтобы шифровать их в файле, но я все же не хочу, чтобы их подделывали вручную, не открывая мое приложение. Когда я сериализую свой объект в файл с помощью простого объекта BinaryFormatter
, используя метод Serialize()
, я вижу читаемые имена типов объектов .net в файле, в котором я сохраняю это. Есть ли способ, чтобы кто-то мог перепроектировать это и посмотреть, что можно сохранить, не используя мою программу? Есть ли способ для кого-то создать небольшое приложение и выяснить, как десериализовать информацию в этом файле? Если да, то как я буду скрывать информацию в этом файле?
Есть ли какие-либо другие советы/рекомендации/рекомендации, которые я должен придерживаться при переходе к сериализации объекта в файл в таком сценарии?
Спасибо заранее!
Ответы
Ответ 1
Если ваш объект реализует интерфейс 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
}
}
И если вы не зашифруете, будет очень легко "прочитать" ваши данные. Очень простое значение, которое вам, возможно, придется потратить пару часов. Если данные, которые вы храните, стоят пару дней, это означает, что это легко, если это всего лишь пару минут, это сложно. Если вы поняли суть.
Очень простой способ шифрования данных - использовать DPAPI Windows через класс ProtectedData
.
Ответ 2
1: с BinaryFormatter, да - вам нужно NonSerialized для событий (если вы не реализуете ISerializable, но это добавляет много работы); однако я в значительной степени уверен, что говорю, что я просто не буду использовать BinaryFormatter здесь. Он не очень прощает ряд изменений в вашем типе. Я бы использовал что-то менее привязанное к внутренним компонентам вашего кода; XmlSerializer; DataContractSerializer, JavaScriptSerializer. Я также могу предложить бинарные альтернативы; NetDataContractSerializer, protobuf-net (мой собственный) и т.д.
2: да, практически с любой реализацией, которая не требует правильного шифрования, если кто-то заботится, что они могут перепроектировать и получить строки. Так что это зависит от того, насколько он скрыт. Простое выполнение существующей сериализации через GZipStream может быть достаточно обфускацией для ваших нужд, НО это просто маска против случайной проверки. Это не сдерживает кого-либо с целью поиска данных.
Если данные должны быть безопасными, вам понадобится надлежащее шифрование, используя либо ключ, который пользователь вводит при запуске приложения, либо что-то вроде сертификата надежно хранится против их профиля пользователя.
Ответ 3
-
Я удаляю события из объектов. Это немного чище.
-
Все, что может быть реконструировано. Просто зашифруйте его при сохранении файла. Это довольно легко сделать. Конечно, ключ шифрования нужно будет хранить в приложении где-нибудь, поэтому, если вы не запутываете свой код, определенный хэкер сможет добраться до него.