动态解密配置,包括实体框架的连接字符串



在谷歌搜索了一段时间后,我找不到任何合适的解决方案来解决我的问题:我加密了我的app.config,所以我在我的appSettings部分得到如下条目:

<add key="Modules" value="xx+LCaY//dRSq3H5z0TClbQbIUd1fm4krjTelMWu9bwkBB2SybkwMqAchYiLP7ss1EEotHtrZwrVtuc+1la5aVwUebCMMbPUj3reE+1XY1Q=" />

此外,我有格式为

的连接字符串
<add name="WorkflowEntries" connectionString="NEuhdfCDdGOeGjkk5PvMDl/Zr+75rOSDqifQZE3X6WJ6ZKjqG6J75O8d0b0j1AeXLVMGtkN7oPldtAWqppFKwCliJ+baMA2NVbkpLlMbhc/IH771MWjlC588USC8RzB7lz+BuXas4RS8kkDXmjENDAlEecLYA2nnkMFlXHJxCCOGA35JXTXWHZeQlFU0dBHVJlSUbqTEGTPETqe2tq/WQMfVpRHsLWlrReBplvGYqVZ+T8XTgaJellN0ZJY4f/UV9R2gjOOwvkBUxRJ2djymlbs4nek/oLuTKyCstd5sRluux8V2odplc98ehmVO0KJ0fBFHIzm4qjByj5pke+kc9FsYSTcqQ4KbBbuXwFI1Oc/1wORHOJbZlu40jioAXVDNiCZQh57cm40G9CRJNAE2Ww=="
providerName="System.Data.EntityClient" />

我可以围绕ConfigurationManager构建一个包装器。AppSettings和ConfigurationManager。ConnectionStrings,但EF不会使用它。是否有一种方法可以"虚拟地操纵"配置,以便应用程序的所有部分都可以访问该配置?

提示:我知道受保护配置的力量。因为我需要轻松地部署我的应用程序,所以这不是我的选择。

我想我完成了。欢迎你发表更多我认为一定存在的有说服力的解决方案。我创建了一个CustomConfigurationManager,将所有需要的逻辑放入其中。你可以这样做:

  1. 类是静态的,所以只需在以下情况下调用CheckConfig()方法您的应用程序启动将检查密钥"加密"appSettings。如果它已经存在,什么也不会发生,否则一切都是的连接字符串connectionStrings部分被加密。密钥"加密"将

  2. 将被添加到配置中以防止下次启动时应用程序再次加密配置。
  3. 在复制-粘贴操作中,我替换了所有出现的ConfigurationManager。AppSettings由CustomConfigurationManager.AppSettings。当从配置(如CustomConfigurationManager.AppSettings["SampleKey"])读取值时

  4. 最关键的部分是将CustomConfigurationManager和Entity Framework结合在一起。我通过手动替换上下文类中的构造函数来做到这一点。在这个过程中,我使用了CustomConfigurationManager。ConnectionStrings indexer .

让我们仔细看看最后一步:

<add name="WorkflowEntries" connectionString="NEuhdfCDdGOeGjkk5PvMDl/Zr+75rOSDqifQZE3X6WJ6ZKjqG6J75O8d0b0j1AeXLVMGtkN7oPldtAWqppFKwCliJ+baMA2NVbkpLlMbhc/IH771MWjlC588USC8RzB7lz+BuXas4RS8kkDXmjENDAlEecLYA2nnkMFlXHJxCCOGA35JXTXWHZeQlFU0dBHVJlSUbqTEGTPETqe2tq/WQMfVpRHsLWlrReBplvGYqVZ+T8XTgaJellN0ZJY4f/UV9R2gjOOwvkBUxRJ2djymlbs4nek/oLuTKyCstd5sRluux8V2odplc98ehmVO0KJ0fBFHIzm4qjByj5pke+kc9FsYSTcqQ4KbBbuXwFI1Oc/1wORHOJbZlu40jioAXVDNiCZQh57cm40G9CRJNAE2Ww=="
providerName="System.Data.EntityClient" />
构造函数

public partial class WorkflowEntries : ObjectContext
{
    #region Constructors
    public WorkflowEntries()
        : base("WorkflowEntries", "WorkflowEntries")
    {
        this.ContextOptions.LazyLoadingEnabled = true;
        OnContextCreated();
    }
...

 public WorkflowEntries()
            : base(CustomConfigurationManager.ConnectionStrings["WorkflowEntries"], "WorkflowEntries")
        {
            this.ContextOptions.LazyLoadingEnabled = true;
            OnContextCreated();
        }

如果你不想操作上下文类,你也可以在实例化上下文时使用接受连接字符串的重载。

这是我的CustomConfigurationManager类。请注意,我删除了加密和解密部分,因为我认为它们与这个问题的上下文中无关。

public static class CustomConfigurationManager
    {
        private static string pwd = "ThisIsNotBestPracticeForStoringPasswords".Select(x => x.ToString() + (x + 2).ToString()).Aggregate((current, next) => current + next);
        public static AppSettingsIndexer AppSettings = new AppSettingsIndexer(pwd);
        public static ConnectionStringsIndexer ConnectionStrings = new ConnectionStringsIndexer(pwd);
        public static void CheckConfig()
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            var appSettings = config.AppSettings;
            var connectionStrings = config.ConnectionStrings.ConnectionStrings;
            if (!appSettings.Settings.AllKeys.Contains("Encrypted"))
            {
                EncryptConfig(pwd, config, appSettings, connectionStrings);
            }
        }
        private static void EncryptConfig(string pwd, Configuration config, AppSettingsSection appSettings, ConnectionStringSettingsCollection connectionStrings)
        {
            foreach (var key in appSettings.Settings.AllKeys)
            {
                appSettings.Settings[key].Value = StringCipher.Encrypt(appSettings.Settings[key].Value, pwd);
            }
            for (int i = 0; i < connectionStrings.Count; i++)
            {
                connectionStrings[i] = new ConnectionStringSettings(connectionStrings[i].Name, StringCipher.Encrypt(connectionStrings[i].ConnectionString, pwd), connectionStrings[i].ProviderName);
            }
            appSettings.Settings.Add("Encrypted", "True");
            config.Save(ConfigurationSaveMode.Modified, true);
        }

        static class StringCipher
        {
            internal static string Encrypt(string plainText, string passPhrase)
            {
                if (plainText.Trim() == "")
                    return "";
                /* Add your encryption stuff here */
            }
            internal static string Decrypt(string cipherText, string passPhrase)
            {
                if (cipherText.Trim() == "")
                    return "";
                /* Add decryption stuff here */
            }
        }
        public class AppSettingsIndexer
        {
            static string pwd;
            public AppSettingsIndexer(string _pwd)
            {
                pwd = _pwd;
            }
            public string this[string index]
            {
                get
                {
                    return StringCipher.Decrypt(ConfigurationManager.AppSettings[index], pwd);
                }
            }
        }
        public class ConnectionStringsIndexer
        {
            static string pwd;
            public ConnectionStringsIndexer(string _pwd)
            {
                pwd = _pwd;
            }
            public string this[string index]
            {
                get
                {
                    var connectionString = ConfigurationManager.ConnectionStrings[index];
                    return new ConnectionStringSettings(connectionString.Name, StringCipher.Decrypt(connectionString.ConnectionString, pwd), connectionString.ProviderName).ToString();
                }
            }
        }
    }

最新更新