TIPS-SqlConnection的ConnectionString保密機制
在設計資料庫相關程式時,連線字串最好能以加密方式存在config檔案裡;再進一步,最好連解密字串的機制都封裝在特定的資料存取元件中,開發人員及呼叫端程式只需傳入SqlCommand或更高階的抽象化資料物件,就可以完成資料庫存取作業,不必也不能得知連線字串的相關細節。
只是依我自己的實務經驗,有時直接傳連線物件(SqlConnection)給呼叫端是較省事的做法(丟一個連線給你自己玩,別來煩我! 是有點不負責任,但元件開發者未必有時間陪著在每個案子中抱著各式不同的需求打滾),連線丟出去了,呼叫端來個SqlConnection.ConnectionString會不會就讓辛苦加密保護的連線字串瞬間曝光呢?
答案是不會,但也可能會!
SqlConnection中有個屬性Persist Security Info,預設值為false,意思是使用SqlConnection.ConnectionString取得的連線字串,密碼的部分會被移除。
既然如此,為什麼又說可能會呢? 經過實測的結果,這個去除密碼的動作,在SqlConnectoin.Open()後才會發生效果(我猜是要等到密碼用過後才將它去掉,其實這可以用設內用外用兩組字串來克服,但SqlConnection的行為是如此設計),若是傳回尚未開啟的SqlConnection,連線字串會原原本本傳回,就失去保護效果囉!
所以,如果在設計上資料存取元件要傳出可用連線給呼叫端,切記"開了再上",就可以靠這個機制多少提供基本的防護,但最安全的方式還是用資料存取層將企業邏輯與實體資料存取完全隔離開來,只是要達成這個理想得付出些代價就是了。
以下是簡單的ConnectionString密碼隱藏效果測試碼:
static void TestConnString()
{
SqlConnection cn =
new SqlConnection("Data Source=(local); Initial Catalog=myDB;
User Id=user1; Password=pwd;");
Console.WriteLine("Before: " + cn.ConnectionString);
cn.Open();
SqlCommand cmd = new SqlCommand("SELECT GETDATE() AS D", cn);
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
Console.WriteLine("Now={0:yyyy-MM-dd HH:mm:ss}", dr["D"].ToString());
Console.WriteLine("After: " + cn.ConnectionString);
cn.Close();
}
【延伸閱讀】MSDN裡關於ADO.NET連線保密的說明