C# .NET5程序加密解密user.config后配置项丢失问题求助
问题原因
- 根本原因是.NET 5+的
System.Configuration.ConfigurationManager包对ClientSettingsSection(也就是项目默认生成的用户设置对应的配置节点类型)的加密解密后序列化逻辑存在缺陷:你当前代码直接将节点作为基类ConfigurationSection处理,调用UnprotectSection()解密后,基类的默认序列化逻辑无法正确识别ClientSettingsSection内部的多配置项集合结构,仅会序列化集合中的最后一个元素到配置文件,同时丢失name属性,就出现了你遇到的只保留最后一个配置项的问题。
解决方案
提供两种可落地的方案,你可以根据需求选择:
方案1:单独加密敏感字段(更推荐,稳定性更高)
不需要加密整个配置节点,只对密码这类敏感字段单独做对称加密后存储,使用时再解密即可,完全规避整个节点加密的兼容性问题:
- 选择AES等对称加密算法,生成固定的密钥存储在程序中
- 保存密码时先加密再写入配置的Password字段
- 读取密码时取出加密字符串解密后使用
这种方案不需要改动配置结构,兼容性更好,也不会出现配置丢失的问题。
方案2:修复原有加密整个节点的逻辑
如果确实需要加密整个用户配置节点,修改你的加解密代码,操作节点时使用强类型的ClientSettingsSection,并在保存前强制标记所有配置元素为已修改:
加密方法修改示例
private void ProtectSettings() { System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal); string provider = "DataProtectionConfigurationProvider"; string sectionName = "userSettings/" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".Properties.Settings"; // 转成强类型的ClientSettingsSection ClientSettingsSection settingsSection = config.GetSection(sectionName) as ClientSettingsSection; if (settingsSection != null) { if (!settingsSection.SectionInformation.IsProtected && !settingsSection.ElementInformation.IsLocked) { settingsSection.SectionInformation.ProtectSection(provider); settingsSection.SectionInformation.ForceSave = true; // 保存前先刷新设置避免缓存问题 Properties.Settings.Default.Reload(); config.Save(ConfigurationSaveMode.Full); Properties.Settings.Default.Reload(); } } }
解密方法修改示例
private static void UnProtectSettings() { System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal); string sectionName = "userSettings/" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".Properties.Settings"; ClientSettingsSection settingsSection = config.GetSection(sectionName) as ClientSettingsSection; if (settingsSection != null) { if (settingsSection.SectionInformation.IsProtected && !settingsSection.ElementInformation.IsLocked) { settingsSection.SectionInformation.UnprotectSection(); // 手动标记所有配置元素为已修改,确保全部被序列化 foreach (SettingsElement setting in settingsSection.Settings) { setting.ElementInformation.IsModified = true; } settingsSection.SectionInformation.ForceSave = true; config.Save(ConfigurationSaveMode.Full); Properties.Settings.Default.Reload(); } } }
内容的提问来源于stack exchange,提问作者Korny86
相关产品推荐
相关产品推荐

