王玉國(guó),王忠良
(通化師范學(xué)院 計(jì)算機(jī)學(xué)院,吉林 通化 134002)
目前數(shù)據(jù)庫(kù)應(yīng)用程序的開(kāi)發(fā)都是采用分層體系結(jié)構(gòu),數(shù)據(jù)庫(kù)和應(yīng)用程序是分開(kāi)的,數(shù)據(jù)庫(kù)部署在服務(wù)器端,應(yīng)用程序部署在客戶(hù)端,目的是提高數(shù)據(jù)的共享性和獨(dú)立性[1], 便于系統(tǒng)的開(kāi)發(fā)和維護(hù).應(yīng)用程序和數(shù)據(jù)庫(kù)的連接是通過(guò)“連接字符串”來(lái)提供信息的.連接字符串由一系列用分號(hào)隔開(kāi)的“名稱(chēng)=值”對(duì)組成的,設(shè)置內(nèi)容取決于希望連接的數(shù)據(jù)源,以及采用的技術(shù)[2].主要內(nèi)容包括希望連接到的數(shù)據(jù)源實(shí)例名字、用戶(hù)名和密碼、默認(rèn)數(shù)據(jù)庫(kù)和集成安全性等信息.連接字符串的配置是每個(gè)數(shù)據(jù)庫(kù)應(yīng)用程序都要面對(duì)的,筆者設(shè)計(jì)的通用客戶(hù)端配置工具就是用來(lái)配置連接字符串的,適用于所有基于.NET的數(shù)據(jù)庫(kù)應(yīng)用程序的開(kāi)發(fā).
許多基于.NET的數(shù)據(jù)庫(kù)應(yīng)用程序開(kāi)發(fā)者,他們或者把連接字符串存放在應(yīng)用程序中,或者存儲(chǔ)在配置文件中[3].
把連接字符串存放在應(yīng)用程序中,優(yōu)點(diǎn)是簡(jiǎn)單,缺點(diǎn)是不靈活.當(dāng)應(yīng)用程序的運(yùn)行環(huán)境發(fā)生變化時(shí),就要修改客戶(hù)端應(yīng)用程序,非常不方便.
把連接字符串存儲(chǔ)到配置文件中,客戶(hù)端應(yīng)用程序運(yùn)行時(shí)讀取配置文件中的連接字符串,這種方法非常靈活、方便.當(dāng)應(yīng)用程序的運(yùn)行環(huán)境發(fā)生變化,直接修改配置文件,而不用修改應(yīng)用程序,就能適應(yīng)運(yùn)行環(huán)境變化.但這種做法也存在一個(gè)問(wèn)題,就是連接字符串的信息暴露在外,登錄到數(shù)據(jù)庫(kù)的信息沒(méi)有加密,降低了系統(tǒng)的安全性.
通過(guò)上面的討論可知:連接字符串的部署應(yīng)具有靈活性和安全性.另外,連接字符串的部署問(wèn)題是數(shù)據(jù)庫(kù)應(yīng)用程序設(shè)計(jì)中的一個(gè)普遍問(wèn)題,應(yīng)具有通用性.通用客戶(hù)端配置工具能夠解決這些問(wèn)題.
通用客戶(hù)端配置工具的工作原理如圖1所示.通用客戶(hù)端配置工具根據(jù)用戶(hù)輸入的配置信息形成連接字符串,測(cè)試成功后進(jìn)行加密,將加密后的連接字符串寫(xiě)入客戶(hù)端應(yīng)用程序配置文件中.這里的客戶(hù)端配置文件指的是以.config為擴(kuò)展名的XML文件.客戶(hù)端應(yīng)用程序的各個(gè)子系統(tǒng)均可以讀取配置文件中加密的連接字符串,解密后用于自身到服務(wù)器的連接字符串.
圖1 通用客戶(hù)端配置工具工作原理
通用客戶(hù)端配置工具的通用性含義是指可以為各個(gè)數(shù)據(jù)庫(kù)應(yīng)用程序配置連接信息并存儲(chǔ)到配置文件中,提供一個(gè)通用的處理方案.
通用客戶(hù)端配置工具的界面應(yīng)該能提供用戶(hù)輸入完成登錄的全部信息,適應(yīng)所有情況,實(shí)現(xiàn)通用性.
客戶(hù)端應(yīng)用程序到服務(wù)器的連接有兩種類(lèi)型,一種是信任連接,一種是非信任連接.信任連接是指只要該用戶(hù)成功登錄到Windows操作系統(tǒng),就可以登錄到SQL Server服務(wù)器,不用再次輸入用戶(hù)名和口令.而非信任連接要求登錄到SQL Server時(shí)再次輸入用戶(hù)名和口令.配置工具的界面上應(yīng)該允許用戶(hù)選擇登錄的連接類(lèi)型.根據(jù)登錄需要,還應(yīng)該允許用戶(hù)輸入配置文件名稱(chēng)、服務(wù)器或數(shù)據(jù)源名稱(chēng)、數(shù)據(jù)庫(kù)名稱(chēng)、用戶(hù)名和密碼.具體工作界面如圖2所示.
圖2 通用客戶(hù)端配置工具界面
圖3 客戶(hù)端配置工具工作流程圖
“配置文件”項(xiàng)是用來(lái)輸入配置文件的名稱(chēng),該文件用來(lái)存儲(chǔ)加密之后的連接字符串信息.“服務(wù)器名”項(xiàng)用來(lái)輸入數(shù)據(jù)源,具體格式是“服務(wù)器名或IP地址實(shí)例名”.“數(shù)據(jù)庫(kù)名”項(xiàng)用來(lái)輸入登錄后訪(fǎng)問(wèn)的數(shù)據(jù)庫(kù)名字.
當(dāng)用戶(hù)選擇信任連接時(shí),“登錄名”和“口令”兩項(xiàng)被禁輸入.“建立連接”是一個(gè)命令按鈕,單擊完成配置工作.
當(dāng)用戶(hù)輸入相關(guān)信息后,單擊“建立連接”按鈕完成配置工作.配置工作的流程圖如圖3所示.
用戶(hù)根據(jù)數(shù)據(jù)庫(kù)應(yīng)用程序、應(yīng)用環(huán)境輸入相應(yīng)配置信息,單擊“建立連接”按鈕后,該工具首先對(duì)用戶(hù)輸入的配置信息進(jìn)行合法性檢查.如果不合法,要求用戶(hù)進(jìn)行修改,如果合法則組合成連接字符串.然后測(cè)試一下能否連接到數(shù)據(jù)源,具體做法是建立SqlConnection對(duì)象,將該連接字符串作為連接屬性值,調(diào)用Open方法后判斷State屬性值,如果值是ConnectionState.Open枚舉值,則能連接到數(shù)據(jù)源.
最后一項(xiàng)工作是加密并寫(xiě)入配置文件.該工作被封裝成一個(gè)用戶(hù)自定義函數(shù)encryptString,該函數(shù)有兩個(gè)參數(shù),一個(gè)存放連接字符串,另一個(gè)存放配置文件名稱(chēng).函數(shù)中首先定義了密鑰,然后定義字節(jié)數(shù)組,通過(guò)內(nèi)存流實(shí)施加密.最后將加密之后的字符串,即密文寫(xiě)入配置文件.具體函數(shù)內(nèi)容如下:
private void encryptString(string myString,string configFileName)
{
string myEncryptKey = "1314";
string encryptStrCnn;
DESCryptoServiceProvider myDesc = new DESCryptoServiceProvider();
byte[] Key = Encoding.Unicode.GetBytes(myEncryptKey);
byte[] encryptData = Encoding.Unicode.GetBytes(myString);
MemoryStream mStream = new MemoryStream();
CryptoStream cStream = new CryptoStream(mStream, myDesc.CreateEncryptor(Key, Key), CryptoStreamMode.Write);
cStream.Write(encryptData, 0, encryptData.Length);
cStream.FlushFinalBlock();
encryptStrCnn = Convert.ToBase64String(mStream.ToArray());
string fileName = Application.StartupPath + @"”+configFileName;
ExeConfigurationFileMap myMap = new ExeConfigurationFileMap();
myMap.ExeConfigFilename = fileName;
try
{
ConnectionStringSettings mySettings = new ConnectionStringSettings("strCnn", encryptStrCnn);
Configuration myConfig = ConfigurationManager.OpenMappedExeConfiguration(myMap, ConfigurationUserLevel.None);
if (myConfig.ConnectionStrings.ConnectionStrings["strCnn"] != null)
myConfig.ConnectionStrings.ConnectionStrings.Remove("strCnn");
myConfig.ConnectionStrings.ConnectionStrings.Add(mySettings);
myConfig.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("Connectionstrings");
}
catch (Exception x)
{
MessageBox.Show(x.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
當(dāng)開(kāi)發(fā)一個(gè)數(shù)據(jù)庫(kù)應(yīng)用程序時(shí),可將通用客戶(hù)端配置工具作為客戶(hù)端系統(tǒng)的一個(gè)子系統(tǒng)來(lái)使用.第一次運(yùn)行應(yīng)用程序或配置環(huán)境發(fā)生變化時(shí),都要運(yùn)行通用客戶(hù)端配置工具來(lái)配置應(yīng)用環(huán)境.這是一款為所有基于.NET數(shù)據(jù)庫(kù)應(yīng)用程序而設(shè)計(jì)的客戶(hù)端配置工具,所以稱(chēng)為通用客戶(hù)端配置工具.有了這款工具,方便了數(shù)據(jù)庫(kù)應(yīng)用程序的開(kāi)發(fā),使程序更具有靈活性,并且增加了對(duì)環(huán)境的適應(yīng)性.