1. 程式人生 > >ConnectionString中的資料庫登入密碼加密

ConnectionString中的資料庫登入密碼加密

使用VS.NET進行WINFORM + MS SQL程式設計,一開始我們都會做以下幾件事情:
  1. 連線到資料庫;(如果你通常都是採用Windows整合驗證,那麼這篇文章可能你不需要看下去了點選看大圖)假設你採用的是SA + 密碼的驗證方式;
  2. 新增新資料來源;VS.NET在這裡提醒我們,連線串裡面包含了敏感資訊;
  3. 把連線字串儲存到程式的配置檔案裡,便於使用和維護;
假設我的專案名字是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點選看大圖privatestaticbyte[] Keys =0x120x340x560x780x900xAB0xCD0xEF };
 5點選看大圖        publicstaticstring EncryptKey ="12345678";
 6點選看大圖        
 7點選看大圖        ///<summary> 8點選看大圖        /// DES加密字串
 9點選看大圖        ///</summary>10點選看大圖        ///<param name="encryptString">待加密的字串</param>11點選看大圖        ///<param name="encryptKey">加密金鑰,要求為8位</param>12點選看大圖        ///<returns>加密成功返回加密後的字串,失敗返回源串</returns>

13點選看大圖publicstaticstring EncryptDES(string encryptString, string encryptKey)
14點選看大圖        {
15點選看大圖            try16點選看大圖            {
17點選看大圖                byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey.Substring(08));
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點選看大圖            catch28點選看大圖            {
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點選看大圖publicstaticstring DecryptDES(string decryptString, string decryptKey)
40點選看大圖        {
41點選看大圖            if (decryptString =="")
42點選看大圖                return"";
43點選看大圖            try44點選看大圖            {
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點選看大圖            catch56點選看大圖            {
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;
點選看大圖    
internalsealedpartialclass Settings {
點選看大圖
點選看大圖        
public Settings() {
點選看大圖            
//// To add event handlers for saving and changing settings, uncomment the lines below:
點選看大圖            
//
點選看大圖            
// this.SettingChanging += this.SettingChangingEventHandler;
點選看大圖            
//
點選看大圖
this.SettingsLoaded +=this.SettingsLoadedEventHandler;
點選看大圖            //
點選看大圖
        }

點選看大圖        
點選看大圖        
privatevoid SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
點選看大圖            
// Add code to handle the SettingChangingEvent event here.
點選看大圖
        }

點選看大圖        
點選看大圖        
privatevoid 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);
點選看大圖        }

點選看大圖
點選看大圖        
publicvoid SetConstr(string connstr1)
點選看大圖        
{
點選看大圖            
this["TestConnectionString"= connstr1;
點選看大圖        }

點選看大圖    }

點選看大圖}

點選看大圖

上面程式碼,public了SetConstr方法,以便於在程式的其他模組還可以有機會動態修改連線串。