zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    rsync用法详细解释
    配置本地yum仓库
    电脑硬件知识
    LVM逻辑卷管理
    前端文本截断
    程序员编写技术文档的新手指南
    JavaScript 是世界上最好的语言?
    一天只工作 3 小时的程序员,已坚持两年
    数据库水平切分方法
    MySQL 笔记整理(1) --基础架构,一条SQL查询语句如何执行
  • 原文地址:https://www.cnblogs.com/zhaobl/p/1421867.html
Copyright © 2011-2022 走看看