在将 class 保存到 xml 文件之前加密属性
Encrypting properties before saving class to xml file
我正在尝试将一些连接字符串作为加密文本保存到我的 class 中的 XML。
这是我的 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);
}
}
}
这就是我保存 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);
}
}
}
}
我的保存工作正常,但它没有将值保存为加密字符串。
我以为这会即时处理它,但它什么也没做:
public string DataSource
{
set => _dataSource = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword);
get => Encryption.SimpleDecryptWithPassword(_dataSource, GlobalConstants.EncryptionPassword);
}
我没有收到任何错误消息,只是没有加密数据。
对我如何在保存某些属性之前对其进行加密有什么建议吗?
编辑:
如果可以阻止,我宁愿不加密整个文件。我只想加密我选择的属性。
您的问题是 XmlSerializer
仅序列化 public 属性和字段 - 以及 [=15= 中的 public 属性] class 全部未加密。来自 docs
XML serialization serializes only the public fields and property values of an object into an XML stream. ...
XML serialization does not convert methods, indexers, private fields, or read-only properties (except read-only collections). To serialize all an object's fields and properties, both public and private, use the DataContractSerializer instead of XML serialization.
因此您的选择是:
为加密成员创建 public 属性,并用 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);
}
演示 fiddle #1 here.
切换到DataContractSerializer
。首先修改你的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
然后修改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);
}
}
生成的属性将全部加密。
演示 fiddle #2 here.
备注:
在 WriteAppSettingsToXmlFile()
中,您不处理 StreamWriter
。这将使文件保持打开状态,并可能在以后导致错误。相反,做:
public static void WriteAppSettingsToXmlFile(AppSetting appSetting)
{
var xs = new XmlSerializer(typeof(AppSetting));
using (var tw = new StreamWriter(GlobalConstants.XmlFile))
{
xs.Serialize(tw, appSetting);
}
}
虽然使用 XmlSerializer
序列化的属性必须 为 public,但您可以通过使用 [=31 标记它们来稍微隐藏它们=],
我正在尝试将一些连接字符串作为加密文本保存到我的 class 中的 XML。
这是我的 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);
}
}
}
这就是我保存 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);
}
}
}
}
我的保存工作正常,但它没有将值保存为加密字符串。
我以为这会即时处理它,但它什么也没做:
public string DataSource
{
set => _dataSource = Encryption.SimpleEncryptWithPassword(value, GlobalConstants.EncryptionPassword);
get => Encryption.SimpleDecryptWithPassword(_dataSource, GlobalConstants.EncryptionPassword);
}
我没有收到任何错误消息,只是没有加密数据。
对我如何在保存某些属性之前对其进行加密有什么建议吗?
编辑: 如果可以阻止,我宁愿不加密整个文件。我只想加密我选择的属性。
您的问题是 XmlSerializer
仅序列化 public 属性和字段 - 以及 [=15= 中的 public 属性] class 全部未加密。来自 docs
XML serialization serializes only the public fields and property values of an object into an XML stream. ...
XML serialization does not convert methods, indexers, private fields, or read-only properties (except read-only collections). To serialize all an object's fields and properties, both public and private, use the DataContractSerializer instead of XML serialization.
因此您的选择是:
为加密成员创建 public 属性,并用
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); }
演示 fiddle #1 here.
切换到
DataContractSerializer
。首先修改你的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
然后修改
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); } }
生成的属性将全部加密。
演示 fiddle #2 here.
备注:
在
WriteAppSettingsToXmlFile()
中,您不处理StreamWriter
。这将使文件保持打开状态,并可能在以后导致错误。相反,做:public static void WriteAppSettingsToXmlFile(AppSetting appSetting) { var xs = new XmlSerializer(typeof(AppSetting)); using (var tw = new StreamWriter(GlobalConstants.XmlFile)) { xs.Serialize(tw, appSetting); } }
虽然使用
XmlSerializer
序列化的属性必须 为 public,但您可以通过使用 [=31 标记它们来稍微隐藏它们=],