Windows Form + SQL 编程:如何对ConnectionString中的数据库登录密码加密
Posted on 2008-04-27 15:22 右手交易 阅读(4097) 评论(19) 编辑 收藏 举报- 连接到数据库;(如果你通常都是采用Windows集成验证,那么这篇文章可能你不需要看下去了)假设你采用的是SA + 密码的验证方式;
- 添加新数据源;VS.NET在这里提醒我们,连接串里面包含了敏感信息;
- 把连接字符串保存到程序的配置文件里,便于使用和维护;
<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的加密方式,也许你喜欢其他的加密算法,反正只要有对应的解密算法,都没问题。
这个是我在网上找的加密工具类,公开了加密和解密的方法。
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="gcEHA/213uBLSOruspbHyQ==""
[注意:不要修改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.修改里面的代码如下:
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方法,以便于在程序的其他模块还可以有机会动态修改连接串。