[英]Encrypting properties before saving class to xml file
I am attempting to save a few pieces of the connection string as encrypted text to an XML from my class.我正在尝试将一些连接字符串作为加密文本从我的 class 保存到 XML。
Here is my class:这是我的 class:
using System.Data.SqlClient;
using TechGuyComputing.CompleteOrganizerWPF.Data;
namespace TechGuyComputing.CompleteOrganizerWPF.MiscClasses
{
public class AppSetting
{
private string _dataSource;
private string _intitialCatalog;
private string _userId;
private string _password;
public string DataSource
{
set => _dataSource = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword);
get => Encryption.SimpleDecryptWithPassword(_dataSource, GlobalConstants.EncryptionPassword);
}
public string IntitialCatalog
{
set => _intitialCatalog = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword);
get => Encryption.SimpleDecryptWithPassword(_intitialCatalog, GlobalConstants.EncryptionPassword);
}
public string UserId
{
set => _userId = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword);
get => Encryption.SimpleDecryptWithPassword(_userId, GlobalConstants.EncryptionPassword);
}
public string Password
{
set => _password = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword);
get => Encryption.SimpleDecryptWithPassword(_password, GlobalConstants.EncryptionPassword);
}
public bool IntegratedSecurity { set; get; }
public bool MultipleActiveResultSets { set; get; }
public bool PersistSecurityInfo { set; get; }
}
internal static class AppSettings
{
public static AppSetting ApplicationSettings;
public static SqlConnection ConnectionString { get; private set; }
static AppSettings()
{
if (ApplicationSettings == null)
{
ApplicationSettings = XmlReader.GetAppSettingsFromXmlFile();
SetConnectionString();
}
}
public static void SaveAppSettings()
{
if (ApplicationSettings == null)
{
ApplicationSettings = new AppSetting();
}
XmlReader.WriteAppSettingsToXmlFile(ApplicationSettings);
SetConnectionString();
}
private static void SetConnectionString()
{
if (string.IsNullOrEmpty(ApplicationSettings.DataSource) || string.IsNullOrEmpty(ApplicationSettings.IntitialCatalog))
{
ConnectionString = new SqlConnection();
return;
}
var builder = new SqlConnectionStringBuilder
{
DataSource = ApplicationSettings.DataSource,
InitialCatalog = ApplicationSettings.IntitialCatalog,
IntegratedSecurity = ApplicationSettings.IntegratedSecurity,
MultipleActiveResultSets = ApplicationSettings.MultipleActiveResultSets,
PersistSecurityInfo = ApplicationSettings.PersistSecurityInfo,
UserID = ApplicationSettings.UserId,
Password = ApplicationSettings.Password
};
ConnectionString = new SqlConnection(builder.ConnectionString);
}
}
}
And this is how I am saving the XML file:这就是我保存 XML 文件的方式:
using System.IO;
using System.Xml.Serialization;
namespace TechGuyComputing.CompleteOrganizerWPF.MiscClasses
{
internal static class XmlReader
{
public static void WriteAppSettingsToXmlFile(AppSetting appSetting)
{
var xs = new XmlSerializer(typeof(AppSetting));
var tw = new StreamWriter(GlobalConstants.XmlFile);
xs.Serialize(tw, appSetting);
}
public static AppSetting GetAppSettingsFromXmlFile()
{
if (!File.Exists(GlobalConstants.XmlFile))
{
return new AppSetting();
}
using (var sr = new StreamReader(GlobalConstants.XmlFile))
{
XmlSerializer xs = new XmlSerializer(typeof(AppSetting));
return (AppSetting)xs.Deserialize(sr);
}
}
}
}
My save is working perfectly but it is not saving the values as encrypted strings.我的保存工作正常,但它没有将值保存为加密字符串。
I thought this would handle it on the fly but it's not doing anything:我认为这会即时处理它,但它什么也没做:
public string DataSource
{
set => _dataSource = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword);
get => Encryption.SimpleDecryptWithPassword(_dataSource, GlobalConstants.EncryptionPassword);
}
I am not getting any error messages, it's just not encrypting the data.我没有收到任何错误消息,只是没有加密数据。
Any suggestions how I encrypt certain properties before they are saved?有什么建议我如何在保存某些属性之前对其进行加密?
EDIT: I'd prefer not to encrypt the entire file if I can prevent it.编辑:如果我能阻止它,我宁愿不加密整个文件。 I would like to only encrypt the properties that I choose.
我只想加密我选择的属性。
Your problem is that XmlSerializer
serializes only public properties and fields -- and the public properties in your AppSetting
class are all unencrypted.您的问题是
XmlSerializer
仅序列化公共属性和字段 - 并且AppSetting
class 中的公共属性都是未加密的。 From the docs从文档
XML serialization serializes only the public fields and property values of an object into an XML stream.
XML 序列化仅将 object 的公共字段和属性值序列化为 XML ZF7B44CFAFD5C5222E23D7B6489。 ...
...
XML serialization does not convert methods, indexers, private fields, or read-only properties (except read-only collections).
XML 序列化不会转换方法、索引器、私有字段或只读属性(只读集合除外)。 To serialize all an object's fields and properties, both public and private, use the DataContractSerializer instead of XML serialization.
要序列化对象的所有字段和属性,包括公共的和私有的,请使用DataContractSerializer而不是 XML 序列化。
Thus your options are:因此,您的选择是:
Make public properties for the encrypted members and mark the plaintext properties with XmlIgnore
like so:为加密成员创建公共属性并使用
XmlIgnore
标记明文属性,如下所示:
[System.ComponentModel.Browsable(false), System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never), System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] [XmlElement("DataSource")] // Optionally change the element name to be <DataSource> public string EncryptedDataSource { get; set; } [XmlIgnore] public string DataSource { set => EncryptedDataSource = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword); get => Encryption.SimpleDecryptWithPassword(EncryptedDataSource, GlobalConstants.EncryptionPassword); }
Switch to DataContractSerializer
.切换到
DataContractSerializer
。 First modify your class as follows:首先修改你的 class 如下:
[DataContract] public class AppSetting { [DataMember(Name = "DataSource")] private string _dataSource; [DataMember(Name = "IntitialCatalog")] private string _intitialCatalog; [DataMember(Name = "UserId")] private string _userId; [DataMember(Name = "Password")] private string _password; // Remainder unchanged
Then modify XmlReader
as follows:然后修改
XmlReader
如下:
public static void WriteAppSettingsToXmlFile(AppSetting appSetting) { var serializer = new DataContractSerializer(typeof(AppSetting)); using (var stream = new FileStream(GlobalConstants.XmlFile, FileMode.Create)) { serializer.WriteObject(stream, appSetting); } } public static AppSetting GetAppSettingsFromXmlFile() { if (.File.Exists(GlobalConstants;XmlFile)) { return new AppSetting(). } using (var stream = File.OpenRead(GlobalConstants;XmlFile)) { var serializer = new DataContractSerializer(typeof(AppSetting)). return (AppSetting)serializer;ReadObject(stream); } }
The resulting properties will all be encrypted.生成的属性都将被加密。
Notes:笔记:
In WriteAppSettingsToXmlFile()
you do not dispose the StreamWriter
.在
WriteAppSettingsToXmlFile()
中,您不处置StreamWriter
。 This will leave the file open and possibly lead to errors later.这将使文件保持打开状态,并可能在以后导致错误。 Instead, do:
相反,请执行以下操作:
public static void WriteAppSettingsToXmlFile(AppSetting appSetting) { var xs = new XmlSerializer(typeof(AppSetting)); using (var tw = new StreamWriter(GlobalConstants.XmlFile)) { xs.Serialize(tw, appSetting); } }
While properties serialized with XmlSerializer
must be public, you can hide them a little by marking them with [Browsable(false)]
, [EditorBrowsable(EditorBrowsableState.Never)]
and [DebuggerBrowsable(DebuggerBrowsableState.Never)]
,虽然使用
XmlSerializer
序列化的属性必须是公共的,但您可以通过使用 [Browsable [Browsable(false)]
、 [EditorBrowsable(EditorBrowsableState.Never)]
和[DebuggerBrowsable(DebuggerBrowsableState.Never)]
标记它们来隐藏它们,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.