即时解密配置,包括Entity Framework的连接字符串

时间:2014-08-06 15:53:13

标签: c# .net app-config configurationmanager

谷歌搜索了一段时间后我无法解决我的问题:我加密了我的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不会使用它。有没有办法实际操纵&#34;配置,所以应用程序的所有部分都将访问这个?

提示:我知道受保护配置的强大功能。由于我需要轻松部署我的应用程序,这对我来说不是一个选项。

1 个答案:

答案 0 :(得分:1)

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

  1. 该类是静态的,因此只需调用CheckConfig()方法 您的应用程序启动时将检查密钥&#34;加密&#34;在 的appSettings。如果它已经存在则没有任何反应,否则全部 appSettings中的值和。中的连接字符串 connectionStrings部分加密。密钥&#34;加密&#34;将 添加到配置中以防止应用程序在下次启动时再次加密配置。

  2. 在复制粘贴操作中,我替换了所有出现的内容 ConfigurationManager.AppSettings by CustomConfigurationManager.AppSettings。从配置中读取时(如CustomConfigurationManager.AppSettings [&#34; SampleKey&#34;])读取值 将被动态解密。

  3. 最关键的部分是将CustomConfigurationManager和Entity Framework结合在一起。我通过手动替换上下文类中的构造函数来完成此操作。在此过程中,我使用了CustomConfigurationManager.ConnectionStrings索引器。

  4. 让我们仔细看看最后一步:使用配置代码段

    <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();
                    }
                }
            }
    
        }