C#配置文件加解密及多項目共享同一配置文件

        忙乎了一天,終於將VS 2005下應用程序配置文件加解密及多項目共用一個配置文件的問題搞定。

        實際要求是:因爲準備編寫一個數學試題庫管理系統,自然考慮到要將數據庫連接字符串保存到配置文件中,C#中當然是保存在App.Config文件。如果你的項目名稱是TestLib,生成的可執行文件是TestLib.EXE,配置文件就是TestLib.EXE.Config。因爲數據庫連接的用戶名和密碼都是放在配置文件中,於是考慮到要將連接字符串加密。同時,爲了方便部署,希望編寫一個程序,能夠按照要求修改連接字符串,並將其保存。這個程序要求必須是一個單獨的EXE文件,僅在部署時纔用到它。用戶平時使用題庫時並不需要用它。

       先解決數據庫連接字符串加解密的問題。
       從“菩提樹下的楊過.Net”的博客中找到了“再談web.config/app.config敏感數據加/解密的二種方法”的文章(http://www.cnblogs.com/yjmyzz/archive/2008/08/22/1274395.html)

加密的方法如下:
//加密web.Config中的指定節
private void ProtectSection(string sectionName)
{
        Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
        ConfigurationSection section = config.GetSection(sectionName);
        if (section != null && !section.SectionInformation.IsProtected)
        {
            section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
            config.Save();
        }
}
//解密web.Config中的指定節
private void UnProtectSection(string sectionName)
{
        Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
        ConfigurationSection section = config.GetSection(sectionName);
        if (section != null && section.SectionInformation.IsProtected)
        {
            section.SectionInformation.UnprotectSection();
            config.Save();
        }
}
雖然是加解密ASP.NET中的Web.Config文件,但只要將
Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
改爲:
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
就可以了。
加密前的配置文件爲:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="MathConnStr" connectionString="Data Source=s10.0.13.100;Initial Catalog=Maths;User ID=Maths;password=5975238"
     providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>
加密後的配置文件爲:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
    <EncryptedData>
      <CipherData>
        <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAnnUA3X3xO0G6yCdMO0YNYwQAAAACAAAAAAADZgAAqAAAABAAAAAhKw7WeiJ2xsjZ1uraDXgDAAAAAASAAACgAAAAEAAAAEKF+hGsklR2pcTePGmtB2igAQAAJDN2SLtXGNKojOGq9ukpFTJg0YrNlgEfaosx7Rxm9spCgKqolicr59L6mthOBeUaVxlx3Rk3YACr7IrWGDj6Pbu4macRf5V5TWSxUv+7dqyljS8uvUuEOLfC25Og4sYqyPsYk/dAnOFAFGbRhDGqlpsvGApOGzgb5vUorzqVVvvK38jdQU/klgqLcDJ5K+WC7GPTcuAfRrCcnvkHA2wPDb+XQGF9Y7ErmoQLazPlBOkIE6qyXQ/6xVEcIc/7FMX3KSgzxTGcITFHBxby/ZIFQ15uauHaxXR1v+gm22pG8o3lLZ1pw/7q5sBpR2wNdlNnl1ExB/t9PK6OFAITV2vOGL8tlx+Gl32+A3EsGGz7GKX3rdpKquugNuBytF3TYYl10k2Z1U/vLMgeUMhG0Ntdb4JJll4VbFmIS9AyBvxM5sO9ZbIbuYavH60BJ2Z1S+ZH1Hm37qjrq0yZLZUetf6RrvDKtkiJcmii6cX3pOt6Ecgdj2vitdN/OJva3JJDhAJOcC49lTwOH2ZZ29tfyuMB/8H/+avchr2e5MwLar2nZ3sUAAAAYczvUuIIqdw7NjlyFowywgYrxRQ=</CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>
</configuration>


        加解密數據庫連接字符串很快就解決了,接下來要解決編寫另外的小程序來修改這個連接字符串。開始考慮到直接做在試題庫的應用程序中。
       從“我們的家園”博客上找到了修改數據庫連接字符串(實際上可以是配置文件中的任何一節)的文章“讀取並修改App.config文件(轉載)”(http://www.cnblogs.com/xshy3412/archive/2007/11/24/971374.html),他也是轉載的喲,從哪兒轉載我就不知道了。這裏面提供了一個修改數據庫連接字符串的方法:
///<summary>
///依據連接串名字connectionName返回數據連接字符串
///</summary>
///<param name="connectionName"></param>
///<returns></returns>
private static string GetConnectionStringsConfig(string connectionName)
{
    string connectionString =
        ConfigurationManager.ConnectionStrings[connectionName].ConnectionString.ToString();
    Console.WriteLine(connectionString);
    return connectionString;
}

///<summary>
///更新連接字符串
///</summary>
///<param name="newName">連接字符串名稱</param>
///<param name="newConString">連接字符串內容</param>
///<param name="newProviderName">數據提供程序名稱</param>
private static void UpdateConnectionStringsConfig(string newName,
    string newConString,
    string newProviderName)
{
    bool isModified = false;    //記錄該連接串是否已經存在
    //如果要更改的連接串已經存在
    if (ConfigurationManager.ConnectionStrings[newName] != null)
    {
        isModified = true;
    }
    //新建一個連接字符串實例
    ConnectionStringSettings mySettings =
        new ConnectionStringSettings(newName, newConString, newProviderName);
    // 打開可執行的配置文件*.exe.config
    Configuration config =
        ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    // 如果連接串已存在,首先刪除它
    if (isModified)
    {
        config.ConnectionStrings.ConnectionStrings.Remove(newName);
    }
    // 將新的連接串添加到配置文件中.
    config.ConnectionStrings.ConnectionStrings.Add(mySettings);
    // 保存對配置文件所作的更改
    config.Save(ConfigurationSaveMode.Modified);
    // 強制重新載入配置文件的ConnectionStrings配置節
    ConfigurationManager.RefreshSection("ConnectionStrings");
}
        有了這個,很快就實現了在應用程序中修改配置文件中已經加密的連接字符串。但考慮到將這個功能放在應用程序中,用戶可能隨便使用,於是考慮將其另外作爲一個可執行文件,這樣,用戶就不會隨便到可執行程序文件夾下執行這個程序了。
聯想到在一個解決方案中創建多個項目,並在主項目中添加對DbConfig項目的引用,DbConfig項目仍然作爲Windows應用程序輸出,可以在主程序輸出目錄中包含DbConfig項目的可執行文件。(作爲類庫項目只包含Dll文件)。
       但很快發現,DbCofnig.Exe文件只能讀取和修改DbCofnig.Exe.Config文件的內容,你把他改成TestLib.Exe,是能讀取TestLib.Exe.Config文件的內容。但主項目TestLib的可執行文件也是TestLib.Exe呀。不可取。

怎麼能做到多項目都能讀取同一個Cofnig文件呢?考慮到ConfigurationManager.OpenExeConfiguration方法的另一個版本:
ConfigurationManager.OpenExeConfiguration(string exePath),它可以指定具體哪個文件。結合Application.ExecutablePath可以獲得可執行文件對應的Config文件。但仍然不行,DbConfig.Exe仍然只能讀取DbConfig.Exe.Config文件。
那就使用Application.StartupPath+@"/Db.config",只讓它讀取指定的Db.Config文件。
       調試了n遍,仍然是“未將對象引用設置到對象的實例”。

       鬱悶ing...,再到網上去找!

       在“若我爲上帝,誰爲衆生”的博客上,找到了這篇文章“再談額外的配置文件讀取和ConfigrationManager.OpenExeConfiguration(exePath)的誤導性錯誤”(http://www.cnblogs.com/telephoner/archive/2008/07/15/1243260.html).
      暈!居然是微軟的Bug。
----------------------------
首先說ConfigrationManager.OpenExeConfiguration(exePath)的問題:
1.此處是一個bug,exePath在msdn的說明中是要讀取的配置文件的路徑,而在生成System.Configuration.Configuration a = System.Configuration.ConfigurationManager.OpenExeConfiguration(exepath)的時候,實際在生成的a對象中,可以看到它的FilePath屬性,讓人大吃一驚,它顯示的路徑是原exePath路徑+.config.
所以a對象中永遠爲空,因爲你的X.config是存在的,但它讀取的卻是X.config.config.

這是否是我們的理解有誤而非Bug呢?
不,在試驗在exePath中填寫.config前面的部分後,提示錯誤,無法讀取該配置文件,即它的ConfigurationManager.OpenExeConfiguration()方法要求exepath必須是一個.config文件!!!

2.這個Bug可能的原因
我猜想,它原來的讀取的方法和類都是針對的配置文件的形式爲:可執行文件文件名+.exe+.config的形式,或者是Machine.config.而這時不需要識別.config的,而當在.net 2.0裏面時候,添加的這個讀取額外配置文件的方法,由於一些失誤,仍然是匹配的原來的老方法,導致它在讀取是自動加上了.config.
---------------------------------------------------------------------------------------------
解決方法
我參考了<Configuration類在網頁實現對web.config的修改>(http://tech.sina.com.cn/s/2008-06-30/1013712947.shtml)的方法
即真假config文件的方法:
1.先在項目的bin/debug目錄下建立一個額外的config文件,即X.config;
2.在同目錄下建立一個X.config.config文件;
3.所有信息都在X.config.config內,即appSettings節點等;
4.然後讀寫都可以了.
-----------------------------------------------------

       於是按照他所提供的方法來,在可執行文件的文件夾下同時存放Db.Config和Db.Config.Config,果然可以,並且將Db.Config文件必須要有,哪怕是個空的都中,刪掉則不行。

      OK! 

 

2008年12月15日晚22:00

 

 

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章