对WinForm的App.config文件进行加密

本文介绍如何在WinForm项目中对App.config文件内的连接字符串进行加密处理,避免敏感信息泄露。通过重命名App.config为Web.config并使用ASP.NETIIS注册工具(Aspnet_regiis.exe)进行加密,最后恢复文件名。同时提供了一种利用DES加密算法手动加密连接字符串的方法,并在运行时自动解密。
转载的,节选主要的


  最近在做一个WinForm的项目,由于采用的是在客户端直接连接数据库的方式,需要在客户端部署App.config,由于使用了Enterprise Library,需要对App.config文件里的connectionStrings片断进行加密处理,搜索MSDN,发现已经有了现成的工具ASP.NET IIS 注册工具 (Aspnet_regiis.exe),可是它只能针对ASP.NET的Web.config文件,难道我们就没有办法了吗?答案当然是否定的。

配置选项

-pdf section webApplicationDirectory 对指定物理(非虚拟)目录中的 Web.config 文件的指定配置节进行解密。
-pef section webApplicationDirectory 对指定物理(非虚拟)目录中的 Web.config 文件的指定配置节进行加密。


    -pdf 和-pef 参数是对指定的物理目录里的Web.config文件进行加密,我们可以先将App.config文件改名为Web.config,通过这两个参数便可以“骗”过系统,让它将指定的配置节进行加密,我们只需要将加密后的文件名改回App.config即可,我们来实验一下:

    第一步:先将目录下的App.config改名为Web.config。

    第二步:打开SDK命令提示,输入命令:aspnet_regiis -pef "配置节" "目录",

例如:
  输入命令:aspnet_regiis -pef "connectionStrings" "E:\开发目录",


由此可见,我们已经完成了任务,现在只需要将Web.config文件名改回App.config即可,在应用程序项目中无需对该文件进行解密操作,.NET框架会自动替我们完成,如果想解密该文件也很简单,在SDK命令提示里输入aspnet_regiis -pdf "配置节" "目录"即可
2008/04/28 11:15
使用VS.NET进行WINFORM + MS SQL编程,一开始我们都会做以下几件事情:

连接到数据库;(如果你通常都是采用Windows集成验证,那么这篇文章可能你不需要看下去了)假设你采用的是SA + 密码的验证方式;
添加新数据源;VS.NET在这里提醒我们,连接串里面包含了敏感信息;
把连接字符串保存到程序的配置文件里,便于使用和维护;
假设我的项目名字是Test,现在当我们打开项目的App.config文件,没错,我的SA密码以明文的方式保存在那里了。
<?xmlversion="1.0"encoding="utf-8" ?>

<configuration>

    <configSections>

    </configSections>

    <connectionStrings>

        <addname="Test.Properties.Settings.TestConnectionString"

            connectionString="Data Source=.;Initial Catalog=TEST_ERP;Integrated Security=False;uid=sa;password=shiny"

            providerName="System.Data.SqlClient" />

    </connectionStrings>

</configuration>
生成EXE,在输出目录下面会产生一个Text.exe.config文件,刚才App.config里面的内容复制到了这个文件,这个是发布的时候需要安装到用户程序路径的,由于是文本文件,我们可以很轻松的根据用户的实际环境修改里面的连接设置。但是,sa的密码保存在里面怎么说也是很令人忐忑的事情。

一个很自然的思路,我们可以把这个密码字符串经过加密再保存,要用的时候再解密,以下是我具体的做法。
我采用的是DES的加密方式,也许你喜欢其他的加密算法,反正只要有对应的解密算法,都没问题。
这个是我在网上找的加密工具类,公开了加密和解密的方法。
1    class CryptClass
2    {
3        //默认密钥向量
4        private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
5        public static string EncryptKey = "12345678";
6        
7        /**//// <summary>
8        /// DES加密字符串
9        /// </summary>
10        /// <param name="encryptString">待加密的字符串</param>
11        /// <param name="encryptKey">加密密钥,要求为8位</param>
12        /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
13        public static string EncryptDES(string encryptString, string encryptKey)
14        {
15            try
16            {
17                byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
18                byte[] rgbIV = Keys;
19                byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
20                DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
21                MemoryStream mStream = new MemoryStream();
22                CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
23                cStream.Write(inputByteArray, 0, inputByteArray.Length);
24                cStream.FlushFinalBlock();
25                return Convert.ToBase64String(mStream.ToArray());
26            }
27            catch
28            {
29                return encryptString;
30            }
31        }
32
33        /**//// <summary>
34        /// DES解密字符串
35        /// </summary>
36        /// <param name="decryptString">待解密的字符串</param>
37        /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
38        /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
39        public static string DecryptDES(string decryptString, string decryptKey)
40        {
41            if (decryptString == "")
42                return "";
43            try
44            {
45                byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);
46                byte[] rgbIV = Keys;
47                byte[] inputByteArray = Convert.FromBase64String(decryptString);
48                DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
49                MemoryStream mStream = new MemoryStream();
50                CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
51                cStream.Write(inputByteArray, 0, inputByteArray.Length);
52                cStream.FlushFinalBlock();
53                return Encoding.UTF8.GetString(mStream.ToArray());
54            }
55            catch
56            {
57                return "";
58            }
59        }
60    }

用你的密码,和自己选择好的密钥(记住要8位字符串)作为参数,调用一下上面的EncryptDES,得到加密后的密码字符串,用它把Test.exe.config里面的密码替换,现在我的config文件里面是:
connectionString="Data Source=.;Initial Catalog=TEST_ERP;Integrated Security=False;uid=sa;
    password=&quot;gcEHA/213uBLSOruspbHyQ==&quot;"

[注意:不要修改App.config里面的内容,这样的话,你在设计期开发环境里面的数据源就连接不上了,而且,要留意别让生成程序的时候VS把你的修改冲掉了,只需要把App.config的属性"复制到输出目录" 设置为不复制就可以了]

下面我们来看看怎么在运行的时候解密出原来的密码:
如果你总是自己用代码创建SQLConnection,那么只需要在创建前把ConnectionString里面的password部分解密就好了,利用上面加密类的解密函数。
问题是我们都是很普遍的使用VS帮我们创建好的强类型的Dataset,和强类型的DataAdapter。而这些DataAdapter已经包含了创建SQLConnection的代码,他们通过读取程序配置的方式获得连接串,方式如下:
    this._connection.ConnectionString = global::Test.Properties.Settings.Default.TestConnectionString;//这个属性是只读的

程序配置是在程序第一次需要读取的时候加载的,我们需要改动它的默认行为,加入解密的操作。

1.展开项目树下面的Properties文件夹,双击Settings.settings节点;
2.在显示的窗口里面点击上面的查看代码,此时将会在你的项目下产生一个Settings.cs源文件;
3.修改里面的代码如下:


namespace Test.Properties {

    using Utilities;
    using System.Data.SqlClient;
    using System.Data.OleDb;
    internal sealed partial class Settings {

        public Settings() {
            // // To add event handlers for saving and changing settings, uncomment the lines below:
            //
            // this.SettingChanging += this.SettingChangingEventHandler;
            //
            this.SettingsLoaded += this.SettingsLoadedEventHandler;
            //
        }
        
        private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
            // Add code to handle the SettingChangingEvent event here.
        }
        
        private void SettingsLoadedEventHandler(object sender,System.Configuration.SettingsLoadedEventArgs e) {
            // Add code to handle the SettingsSaving event here.
            SqlConnectionStringBuilder ConnSb = new SqlConnectionStringBuilder();
            string s1;
            ConnSb.ConnectionString = this["TestConnectionString"].ToString();
            ConnSb.Password = CryptClass.DecryptDES(ConnSb.Password, CryptClass.EncryptKey);
            s1 = ConnSb.ConnectionString;

            SetConstr(s1);
        }

        public void SetConstr(string connstr1)
        {
            this["TestConnectionString"] = connstr1;
        }
    }
}

上面代码,public了SetConstr方法,以便于在程序的其他模块还可以有机会动态修改连接串。

转载于:https://www.cnblogs.com/Deckard/archive/2009/07/02/1515531.html

<think> 首先,用户的问题是关于C# WinForm中的APP.config和exe.config文件的介绍、区别及使用方法。用户提供了几个引用,我需要参考这些引用,并在回答中自然地添加引用标识。 引用内容: - [^1]: 讨论了Settings.settings和app.config/exe.config的不同步问题,指出设计时文件app.config,运行时文件是exe.config。 - [^2]: 描述了如何配置App.config文件,包括添加appSettings元素。 - [^3]: 提到在WinForm中读写app.config中的connectionStrings。 - [^4]: 展示了默认的app.config代码。 我的回答需要: - 结构清晰,逐步解决问题。 - 使用中文。 - 所有行内数学表达式用$...$格式(但在这个主题中,可能没有数学表达式)。 - 独立公式用$$...$$格式单独成段(同样,可能不适用)。 - 生成相关问题。 - 在引用段落末尾添加引用标识,如[^1]。 回答结构: 1. **介绍APP.config和exe.config**:解释它们是什么。 2. **区别**:对比两者的角色和使用场景。 3. **使用方法**:如何配置和使用,包括读写操作。 4. **常见问题**:如不同步问题(引用[^1])。 5. **生成相关问题**:在末尾添加相关问题。 关键点从引用: - APP.config是设计时文件,位于项目源码中。 - exe.config是运行时文件,在编译后生成在bin/Debug或bin/Release目录下。 - 不一致的原因:Visual Studio的编译处理、user.config覆盖等(引用[^1])。 - 配置方法:添加appSettings或connectionStrings(引用[^2],[^3])。 - 默认配置(引用[^4])。 逐步解答: - **介绍**:APP.config是配置文件,用于WinForm应用程序的设计时设置。exe.config是编译后生成的配置文件,应用程序运行时使用。 - **区别**: - APP.config:源码中的XML文件,修改需要重新编译。 - exe.config:编译后的副本,应用程序加载时读取。 - 区别在于位置和作用域:APP.config用于开发,exe.config用于部署。 - **使用方法**: - 配置:在App.config中添加元素如appSettings或connectionStrings(引用[^2],[^3])。 - 读取:使用ConfigurationManager类来访问设置。 - 读写:对于connectionStrings,有特定方法读写(引用[^3])。 - 注意事项:修改APP.config后,exe.config可能不会自动更新,需要调整生成行为(引用[^1])。 确保引用:在提到相关点时添加[^n]。 生成相关问题:在末尾添加,如: 1. 如何解决APP.config修改后exe.config不同步的问题? 2. 如何在运行时修改WinForm应用的配置? 3. APP.config中的安全注意事项? 最后,以相关问题结束。 </think> ### C# WinFormAPP.config和exe.config的介绍、区别及使用方法 在C# WinForm开发中,配置文件是管理应用程序设置的重要手段。APP.config和exe.config是两个关键文件,它们共同协作实现配置管理,但角色和用法有显著差异。下面我将逐步解释它们的定义、区别和使用方法,确保内容清晰可靠。 #### 1. **介绍** - **APP.config**: 这是设计时配置文件,位于WinForm项目的源码目录中(通常与.csproj文件同级)。它是一个XML格式的文件,用于存储应用程序的初始设置,如数据库连接字符串、自定义键值对或运行时环境参数。[^4] 例如,默认的APP.config内容可能包括.NET框架版本声明: ```xml <?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /> </startup> </configuration> ``` 开发人员直接编辑此文件来控制编译前的配置。 - **exe.config**: 这是运行时配置文件,在编译过程中由Visual Studio自动生成。它存放在输出目录(如`bin/Debug`或`bin/Release`)下,文件名为`YourApp.exe.config`(其中`YourApp.exe`是应用程序的可执行文件)。应用程序运行时加载此文件来获取配置值,而非直接使用APP.config。[^1] 例如,如果APP.config包含连接字符串,编译后exe.config会包含相同的设置。 #### 2. **区别** APP.config和exe.config的核心区别在于角色和作用域: - **设计时 vs. 运行时**: - APP.config是源码文件,开发阶段编辑(如添加appSettings或connectionStrings)。[^2][^3] - exe.config是编译输出文件,运行时加载。应用程序启动时读取exe.config,如果不存在user.config(用户级配置文件),则使用exe.config作为默认值。 - **位置和更新机制**: - APP.config在项目中手动修改,修改后需要重新编译才能同步到exe.config。 - exe.config由Visual Studio在编译时从APP.config复制生成。如果APP.config更改后exe.config未更新,可能导致不同步问题。[^1] - **优先级的区别**: - 运行时,应用程序优先加载user.config(用户范围的配置文件),其次是exe.configAPP.config本身不参与运行时加载。 - **常见不一致原因**(引用[^1]): - Visual Studio编译时使用特殊逻辑处理Settings.settings,可能生成变体。 - MSBuild编译过程未正确处理同步。 - user.config覆盖设置(用户级配置优先级高于应用级)。 简单总结:APP.config是“蓝图”,exe.config是“执行副本”;前者用于开发,后者用于部署。 #### 3. **使用方法** 使用这些配置文件主要包括配置、读取和写入操作。确保在项目中添加App.config文件(如果不存在:右键项目 > “添加” > “新建项” > “应用程序配置文件”)[^2]。 - **配置设置**: - **AppSettings(自定义键值对)**:在APP.config中添加`<appSettings>`元素。例如: ```xml <configuration> <appSettings> <add key="ApiUrl" value="https://api.example.com" /> <add key="Timeout" value="30" /> </appSettings> </configuration> ``` 编译后,exe.config会包含相同内容。[^2] - **ConnectionStrings(数据库连接)**:在APP.config中添加`<connectionStrings>`元素。这在WinForm数据绑定中尤其常用(如DataGridView向导生成的数据源)[^3]: ```xml <configuration> <connectionStrings> <add name="MyDbConnection" connectionString="Data Source=server;Initial Catalog=db;User ID=user" providerName="System.Data.SqlClient" /> </connectionStrings> </configuration> ``` - **读取设置**: 使用`System.Configuration`命名空间中的`ConfigurationManager`类: - 读取AppSettings: ```csharp string apiUrl = ConfigurationManager.AppSettings["ApiUrl"]; ``` - 读取ConnectionStrings: ```csharp string connStr = ConfigurationManager.ConnectionStrings["MyDbConnection"].ConnectionString; ``` 此方法默认加载exe.config文件。 - **写入设置**: - **运行时修改**:APP.config不应在运行时直接修改,因为这需要重新编译。但可以更新exe.config或user.config(用户级文件)。 - 例如,修改ConnectionString(需管理员权限): ```csharp var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); config.ConnectionStrings.ConnectionStrings["MyDbConnection"].ConnectionString = "新连接字符串"; config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection("connectionStrings"); // 刷新缓存 ``` 这会更新exe.config文件。[^3] - **确保同步的解决方案**(引用[^1]): - **方法1:调整生成行为**:在Visual Studio中,确保APP.config被复制到输出目录。修改项目文件.csproj),添加: ```xml <ItemGroup> <None Update="App.config"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup> ``` 这强制编译时将APP.config复制为exe.config。 - **方法2:使用Settings.settings**:对于用户级设置,Visual Studio的Settings.settings设计器会自动同步到user.config,避免exe.config冲突。 #### 4. **注意事项** - **安全问题**:APP.config和exe.config包含敏感信息(如连接字符串),应加密处理(使用`ProtectedConfigurationProvider`)。 - **部署问题**:发布应用时,exe.config随EXE文件分发;如果APP.config更改,必须重新编译。 - **调试技巧**:如果设置未生效,检查`bin`目录下的exe.config是否最新版本。 通过以上步骤,您可以高效管理WinForm配置。如需深入,参考提供的引用源。[^1][^2][^3][^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值