Asp.Net Form验证不通过,重复登录
2014-04-14 19:57
399 查看
问题产生根源:
当然,其实应该需要保持线上所有机器环境一致!可是,写了一个小程序。使用的是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 旧加密方式. 马上解决...
相关文章推荐
- 树莓派通过ADC0832采集模拟量
- 报表,联机分析处理控件,OLAP, 立方体, Cube展示控件RadarCube ASP.NET OLAP Chart
- 设置webconfig 解决asp.net上传文件过大问题
- ASP.NET MVC Filters 4种默认过滤器的使用
- asp.net打印网页后自动关闭网页【无需插件】
- 基于@AspectJ注解的纯POJO Spring 2.x Aop
- asp.net SqlParameter关于Like的传参数无效问题
- asp.net页生命周期图解---msdn
- [翻译]创建ASP.NET WebApi RESTful 服务(9)
- 学习笔记--asp.net页生命周期(转自msdn,仅为自己学习存储和有意读者使用)
- asp.net mvc return file result
- 科讯CMS--将自己的ASP加进去
- ASP.NET MVC 后台控制器向前台传递数据的几种方式
- 在win 2008 R2环境下如何使用iis7.0正确发布ASP。NET项目
- 在win 2008 R2环境下如何使用iis7.0正确发布ASP。NET项目
- ASP.NET页面之间传递值的几种方式
- 给Asp.net MVC Forms 验证设置角色访问控制
- OWASP WebGoat---安全测试学习笔记(三)---Ajax安全
- Using Plupload in ASP.NET
- [译]Asp.net MVC 之 Contorllers(一)