您的位置:首页 > 编程语言 > C#

C#配置文件加解密及多项目共享同一配置文件(转载)

2009-03-25 22:42 501 查看
        忙乎了一天,终于将VS 2005下应用程序配置文件加解密及多项目共用一个配置文件的问题搞定。

        实际要求是:因为准备编写一个数学试题库管理系统,自然考虑到要将数据库连接字符串保存到配置文件中,C#中当然是保存在App.Config文件。如果你的项目名称是TestLib,生成的可执行文件是TestLib.EXE,配置文件就是TestLib.EXE.Config。因为数据库连接的用户名和密码都是放在配置文件中,于是考虑到要将连接字符串加密。同时,为了方便部署,希望编写一个程序,能够按照要求修改连接字符串,并将其保存。这个程序要求必须是一个单独的EXE文件,仅在部署时才用到它。用户平时使用题库时并不需要用它。

       先解决数据库连接字符串加解密的问题。

       从“菩提树下的杨过.Net”的博客中找到了“再谈web.config/app.config敏感数据加/解密的二种方法”的文章(/article/4607603.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文件(转载)”(/article/5835124.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)的误导性错误”(/article/6276795.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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: