當然,其實應該需要保持線上所有機器環境一致!可是,寫了一個小程序。使用的是4.5,aysnc/await實在太好用了,真心不想把代碼修改回去。
so,動了念頭,在這臺服務器上裝個4.5,ms不是說了么,4.5和4.0是高度兼容的。。。。。。
一臺服務器在安裝.net framework 4.5 之后,在該服務器所部署的網站(使用.net framework 4,未修改任何配置,分布式環境),
網站在這臺服務器上登錄之后,打開其他服務器的任何站點,form驗證過不去,導致重復登錄,反之亦然.
為什么會導致重復登錄問題?
很簡單能推斷出是在這個機器上安裝了4.5 ,某些組件的變動,導致form驗證的加解密方式有變動.使得2臺機器生成的登錄cookie內容不一致,不能相互解析.
能影響到.net對form加解密產生不同作用的地方無非2個.
1.本身代碼的bug,兼容性問題問題。
2.配置影響(如web.config中的authentication,machineKey等).
1嘛,基本不可能,ms沒這么渣,那就只能從2下手,但是具體什么配置影響到,就不得而知了.
通過參數配置,如果有改變,那對加解密產生的改變都是相符的. so,我們分析一下加密的方法,找出不同,通過參數來兼容這些修改.那問題就解決了.
form驗證相關的方法,都在System.Web.Security.FormsAuthentication中.
通過調用加密方法在4.5上生成加密字符串,丟到4.0的機器上解密,不通過,提示加密字符串驗證不通過.
so,我們看看加密方法中做了什么
加密方法:
省略部分代碼,剩下的關鍵代碼。
public static string Encrypt(FormsAuthenticationTicket ticket){    return Encrypt(ticket, true);}internal static string Encrypt(FormsAuthenticationTicket ticket, bool hexEncodedTicket){    byte[] clearData = MakeTicketIntoBinaryBlob(ticket);        if ((_PRotection == FormsProtectionEnum.All) || (_Protection == FormsProtectionEnum.Encryption))        {            clearData = MachineKeySection.EncryptOrDecryptData(true, clearData, null, 0, clearData.Length, false, false, IVType.Random);        }    }    return CryptoUtil.BinaryToHex(clearData);}然后我們繼續深入到MakeTicketIntoBinaryBlob中查看
private static byte[] MakeTicketIntoBinaryBlob(FormsAuthenticationTicket ticket){    if (!AppSettings.UseLegacyFormsAuthenticationTicketCompatibility)    {        return FormsAuthenticationTicketSerializer.Serialize(ticket);    }  ........................}對比4,4.5中MakeTicketIntoBinaryBlob方法代碼,發現4.5的源代碼中多了AppSettings.UseLegacyFormsAuthenticationTicketCompatibility這么一個開關配置.
系統默認值為flase,so.在4.5中得到的加密字符串來自FormsAuthenticationTicketSerializer.Serialize(ticket).而4中是在后續代碼中.
so,增加配置<add key="aspnet:UseLegacyFormsAuthenticationTicketCompatibility" value="true" /> 兼容到這部分.
然后,我們繼續看MachineKeySection.EncryptOrDecryptData(true, clearData, null, 0, clearData.Length, false, false, IVType.Random);
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, bool useValidationSymAlgo, bool useLegacyMode, IVType ivType){    return EncryptOrDecryptData(fEncrypt, buf, modifier, start, length, useValidationSymAlgo, useLegacyMode, ivType, !AppSettings.UseLegacyEncryption);}很熟悉,又看到!AppSettings.UseLegacyEncryption開關配置.進入EncryptOrDecryptData方法中能看到這個參數影響到使用不同的加密方式.
同上,增加配置<add key="aspnet:UseLegacyEncryption" value="true" />兼容到這部分.
再次調用Encrypt方法生成加密字符串,丟到4.0機器上.哇,能解密成功了.
當然,實際解決起來,走了不少彎路,周五晚上發現問題,查了一晚上,未果,但是有思路了.后又周一查了2個小時,終于搞定這個問題.
相關說明:
有關安全更新 2638420 的部署指南,請參見 MS11-100
如何配置 ASP.NET 中的舊加密模式
看了上面一個,好傻...如果發現問題的時候,之后搜索asp.net 舊加密方式. 馬上解決...
新聞熱點
疑難解答