当然,其实应该需要保持线上所有机器环境一致!可是,写了一个小程序。使用的是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 旧加密方式. 马上解决...
新闻热点
疑难解答