然后在程序中通過system.configuration.configurationsettings.appsettings ["connstr"]方法讀取,這樣大大提高了程序訪問的方便性.但這種方法也潛在產(chǎn)生了數(shù)據(jù)庫的安全隱患,因?yàn)橹灰茏x到這個(gè)配置文件的用戶,稍懂計(jì)算機(jī)知識的人立即就能知道數(shù)據(jù)庫的登陸信息,并進(jìn)行登錄數(shù)據(jù)庫,從而進(jìn)行各種操作.雖然服務(wù)器有許多安全設(shè)置,但是,現(xiàn)在的網(wǎng)絡(luò)安全還不是十分可靠,在安全方面還是需要多下點(diǎn)功夫.如果我們能將配置文件寫入以下的值:
<appsettings>
<add key="connstr" value="22c25fee2659a7f295eb4963aaae2d5474aa434036cc43892128e73112bc2b2c568e8d3f53efc7ac0f6413627d9d036e43a3e57c1953e21167760d12e59e3443" />
</appsettings>
就算是網(wǎng)站源碼被黑客下載了,或者web服務(wù)器上的配置文件泄露了出去,但是這段代碼又有誰能譯出原文是什么呢?
中間這些無規(guī)律的字符可不是簡單的字節(jié)轉(zhuǎn)換得到的.我們完全可以借助.net提供的強(qiáng)大安全功能實(shí)現(xiàn)des加密數(shù)據(jù)庫連接信息.
對于des加密的理論這里就不多講了,可以查閱其它資料,我們這里只講它的實(shí)現(xiàn)應(yīng)用.如果朋友們能理解并且相信它的加密強(qiáng)度:那么下邊我就給大家多費(fèi)點(diǎn)口舌談一談具體的實(shí)現(xiàn)方法:
首先,我們?yōu)榱碎_發(fā)及以后布署的方便性,我們最好能寫一個(gè)小的工具進(jìn)行加密及配置文件的寫入,因?yàn)閿?shù)據(jù)庫布署在不同的機(jī)器上連接字符串改一次,如果手工生成加密字符串再修改配置文件,這種重復(fù)的勞動,可能過段時(shí)間,你就會受不了,所以我們找一個(gè)一勞永逸的方法(有點(diǎn)夸張,沒有什么東西能一勞永逸喲),自己動手寫個(gè)小工具.我也試找個(gè)地方把工具及實(shí)現(xiàn)方法上傳至網(wǎng)上,如果有興趣的朋友,可以看看.
先看看加解密的關(guān)鍵方法:加密方法及解密方法如下,如果不能完全不能明白這兩個(gè)方法也不影響我們的使用:我們只需要知道調(diào)用規(guī)則即可
#region 加密方法
//ptoencrypt為需要加密字符串,skey為密鑰
public string encrypt(string ptoencrypt, string skey)
{
descryptoserviceprovider des = new descryptoserviceprovider();
//把字符串放到byte數(shù)組中
//原來使用的utf8編碼,我改成unicode編碼了,不行
byte[] inputbytearray = encoding.default.getbytes(ptoencrypt);
//建立加密對象的密鑰和偏移量
//使得輸入密碼必須輸入英文文本
des.key = asciiencoding.ascii.getbytes(skey);
des.iv = asciiencoding.ascii.getbytes(skey);
memorystream ms = new memorystream();
cryptostream cs = new cryptostream(ms, des.createencryptor(),cryptostreammode.write);
cs.write(inputbytearray, 0, inputbytearray.length);
cs.flushfinalblock();
stringbuilder ret = new stringbuilder();
foreach(byte b in ms.toarray())
{
ret.appendformat("{0:x2}", b);
}
ret.tostring();
return ret.tostring();
}
#endregion
#region 解密方法
//ptodecrypt為需要解密字符串,skey為密鑰
public string decrypt(string ptodecrypt, string skey)
{
descryptoserviceprovider des = new descryptoserviceprovider();
byte[] inputbytearray = new byte[ptodecrypt.length / 2];
for(int x = 0; x < ptodecrypt.length / 2; x++)
{
int i = (convert.toint32(ptodecrypt.substring(x * 2, 2), 16));
inputbytearray[x] = (byte)i;
}
//建立加密對象的密鑰和偏移量,此值重要,不能修改
des.key = asciiencoding.ascii.getbytes(skey);
des.iv = asciiencoding.ascii.getbytes(skey);
memorystream ms = new memorystream();
cryptostream cs = new cryptostream(ms, des.createdecryptor(),cryptostreammode.write);
cs.write(inputbytearray, 0, inputbytearray.length);
cs.flushfinalblock();
//建立stringbuild對象,createdecrypt使用的是流對象,必須把解密后的文本變成流對象
stringbuilder ret = new stringbuilder();
return system.text.encoding.default.getstring(ms.toarray());
}
#endregion
注意,skey為一個(gè)長度為八位的字符串,加密和解密時(shí)必須一致.為了加強(qiáng)模糊度,我們可以在程序初始化時(shí)用不可打印ascii碼組合連接得到skey,如下所示:
int[] tmp=new int[8]{23,234,195,165,201,240,143,198};
foreach(int i in tmp)
{
skey+=((char)i).tostring();
}
利用我們寫的工具進(jìn)行配置文件的加解密(該工具中也涉及到一些xml操作方法),既可讀出原來的配置信息,又可以改寫或者添加配置節(jié).有一處我們還要注意,就是讀取原來的配置信息時(shí),不能讓密碼信息呈現(xiàn)出來,也不能呈現(xiàn)為"******"的掩碼形式,網(wǎng)上好多的工具軟件,比如密碼查看器,只要往密碼框上一放.密碼原文立即暴露無遺.而我們要做到用這類軟件查看到的還是一些"******"字符,但是在用戶對讀出密碼不做修改時(shí)繼續(xù)保持原來的密碼.那么該怎么實(shí)現(xiàn)呢.這點(diǎn)小技巧,留給朋友們在代碼中找找看吧.
下面說說我們在web程序中該怎樣使用加密后的連接信息呢,也很簡單,用原來的方法讀取配置文件connstr節(jié)信息后,再進(jìn)行上面方法解密,當(dāng)然解密用的密鑰也必須和加密時(shí)一致.解密成功后就ok了!
代碼如下:
string strconn = system.configuration.configurationsettings.appsettings["connstr"];
connstr = decrypt(strconn,skey);
conn=new sqlconnection(connstr);
這些代碼各位一看就會,我就不唾沫亂飛了吧.
找了一下,發(fā)現(xiàn)這個(gè)blog沒有上傳文件的地方,本來想著把我寫好的現(xiàn)成工具及源代碼上傳上來,看來想做個(gè)雷鋒也難,沒辦法,那就先暫時(shí)把源碼貼出來,有興趣的朋友自己編譯一個(gè)看看.
源碼就放在下一篇吧,這樣看起來統(tǒng)一.
如果各位朋友還有更好的辦法,那我們不妨再多交流交流!
新聞熱點(diǎn)
疑難解答
圖片精選