當(dāng)你準(zhǔn)備將web應(yīng)用程序從asp.net 1.1升級(jí)到asp.net 2.0,你將面對(duì)這樣一個(gè)cookie問題:在asp.net 1.1應(yīng)用程序中客戶端保存的所有cookie將失效。
博客園也遇到了這樣的問題,對(duì)博客園來說,意味著所有使用cookie的用戶都需要重新登錄,雖然這不是一個(gè)很大的問題,但的確給大家?guī)砹寺闊绻浟嗣艽a,將更加麻煩。
對(duì)于一個(gè)非常重視用戶滿意度的網(wǎng)站來說,應(yīng)該努力去解決這個(gè)問題。博客園希望盡可能減少升級(jí)帶來的影響,所以這兩天我一直在研究這個(gè)問題并找到了解決方法。
問題的原因是:當(dāng)程序從asp.net 1.1升級(jí)到于asp.net 2.0后,asp.net 2.0使用新的算法與密鑰對(duì)客戶端發(fā)送過來的cookie進(jìn)行解密,這樣導(dǎo)致asp.net中生成的cookie在asp.net 2.0中失效。在asp.net 1.1中,使用3des算法對(duì)cookie的內(nèi)容進(jìn)行加密,而在asp.net 2.0中默認(rèn)使用advanced encrypted standards (aes)算法進(jìn)行解密,這是引起問題的原因之一,通過相應(yīng)的設(shè)置可以將asp.net 2.0中將cookie加密算法改為3des,只需在web.config中加上:.但這樣做之后問題依然存在,因?yàn)榻饷軙r(shí)除了需要相同的算法,還需要相同的密鑰。如果沒有在machinekey中指定密鑰,asp.net 2.0會(huì)默認(rèn)會(huì)使用隨機(jī)生成的密鑰,這個(gè)隨機(jī)密鑰由system.web.httpruntime.setautogenkeys()生成并存儲(chǔ)于system.web.httpruntime.s_autogenkeys中,通過反射你可以獲取這個(gè)值。asp.net 1.1的machinekey是在machine.config中進(jìn)行設(shè)置的,默認(rèn)也是使用隨機(jī)密鑰:.問題就出在不同的隨機(jī)密鑰上。如果你在原來的asp.net 1.1中指定了密鑰,那就不存在這個(gè)問題了,但一般在使用web farm時(shí),才會(huì)考慮這一點(diǎn)。所以通常情況都是使用隨機(jī)密鑰。asp.net會(huì)為不同的應(yīng)用程序生成不同的隨機(jī)密鑰,這個(gè)客戶端cookie失效問題會(huì)出一在很多情況下,比如:重裝系統(tǒng)、將asp.net應(yīng)用程序移至另外一臺(tái)計(jì)算機(jī),將web應(yīng)用程序移到不同的虛擬目錄中等等。
如何解決這個(gè)問題呢?
原理很簡(jiǎn)單,只要我們知道在asp.net 1.1中隨機(jī)生成的密鑰的值,然后在asp.net 2.0應(yīng)用程序的web.config中進(jìn)行指定就行了,這里的密鑰有兩個(gè):一個(gè)是加密密鑰decryptionkey,一個(gè)是散列計(jì)算密鑰validationkey(防止cookie被中途篡改)。假如我們知道密鑰分別為:x、y,那在web.config進(jìn)行如下設(shè)置就能解決問題:而難題就在于如何得到asp.net 1.1中隨機(jī)生成的密鑰的值。密鑰存儲(chǔ)在lsa(windows local security authority)中,但我沒找到可以從lsa獲取密鑰的方法。
由于博客園主要是解決登錄cookie的問題,而這個(gè)cookie是在system.web.security.formsauthentication. setauthcookie(string username, bool createpersistentcookie)中生成的,所以我就從asp.net 1.1的system.web.security.formsauthentication的源代碼下手,發(fā)現(xiàn)了system.web.configuration.machinekey,經(jīng)過進(jìn)一步對(duì)machinekey的源代碼進(jìn)行研究,在machinekey的machinekeyconfig中發(fā)現(xiàn)了兩個(gè)密鑰分別存在于s_validationkey與s_odes這兩個(gè)私有靜態(tài)成員中(發(fā)現(xiàn)這個(gè)費(fèi)了不少功夫),validationkey的值直接存儲(chǔ)于s_validationkey中,而decryptionkey存儲(chǔ)于s_odes.key中。由于machinekey是internal class,machinekeyconfig是私有類型,那兩個(gè)成員是私有靜態(tài)成員,無法直接訪問。這時(shí),該是。net中強(qiáng)大的反射功能發(fā)揮作用的時(shí)候了。通過反射得到這兩個(gè)值,需要注意的是這兩個(gè)值的類型是byte[],通過測(cè)試發(fā)現(xiàn)直接轉(zhuǎn)換成字符串生成的密鑰無效,需要通過反射調(diào)用system.web.configuration.machinekey.bytearraytohexstring(byte[], int32) 轉(zhuǎn)換成字符串。
今天晚上終于解決了這個(gè)問題,好興奮!中途幾次想放棄,但想到在博客園程序升級(jí)到asp.net 2.0后,會(huì)因?yàn)檫@個(gè)問題給很多人帶來麻煩,雖然只需要重新登錄一下就行了,但我還是覺得要解決這個(gè)問題,做程序開發(fā)不就是盡可能給用戶帶來方便嗎?
解決了這個(gè)問題就為博客園網(wǎng)站升級(jí)到asp.net 2.0作好了進(jìn)一步的準(zhǔn)備。
新聞熱點(diǎn)
疑難解答
圖片精選