在ASP.NET里面,View State使用较为广泛。它作为一个隐藏字段,可以帮助服务端”记住“客户端的改变,这样客户端 收到服务器对PostBack的响应后,仍然可以展现在PostBack之前设定的值 (具体参见http://msdn.microsoft.com/en-us/library/bb386448(v=vs.100).aspx )

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="..." />

为了防止恶意客户端的PostBack里的ViewState被解读,ASP.NET会用消息验证码(MAC)来检查每个ViewState。可是一旦服务器无法正确解释正常客户端PostBack回来的ViewState时,整个应用都会停止工作。比如出现 ”Validation of viewstate MAC failed” 的错误。

通常来说,一旦这样的错误出现,首先会考虑以下几种情况:

1. 是不是有多台Web Server在负载均衡情况下运行。如果是的话,需要各台服务器使用相同的MAC进行ViewState的加密和解密工作。否则如果这个负载均衡环境没有完全做的Session Affinity,这种错误就会出现。

2. 测试本机访问是否也有这种错误。如果是的话,除了尝试重新产生新的MachineKey (参见http://blogs.msdn.com/b/amb/archive/2012/07/31/easiest-way-to-generate-machinekey.aspx ),也可以用Process Monitor在复现问题的时候跟踪文件和注册表的访问,看看是不是因为W3WP.exe缺少权限而不能获取和MachineKey相关的信息。

3. 在客户端和服务器端抓取网络包,比较ViewState是否被中间设备改动。这种情况不多见,但是也遇到过。算是复杂的一种情况。如果连接是SSL的,抓包没有办法查看,客户端就要使用Fiddler,而服务端需要采取额外诊断日志或者Debug的方法。

4. 和具体代码相关,尤其是对ViewStateUserKey有特殊设置。

这里谈到的是一个在一个大型的生产应用环境里遇到的实际问题,和上面的情况有关,但有些有趣的变化。

这个环境里面有多台Web 服务器,采用了负载均衡方式。在客户试图登录时(login.aspx),总是会遇到”Validation of viewstate MAC failed”的错误。

起初,怀疑是不同机器上WebAppication的MachineKey不一样引起的。检查了Web.Config里的配置,各个机器都是一样:

  1. <system.web>
  2.  
  3. <machineKey decryptionKey="6284D74F8D9745C38712047622FFA047B02CA5C4049FB74E,IsolateApps" validationKey="137B974DC38A910D946AAF3ADF1D0386072170236F39C8165098035126FE7DFDF68C7BD3646052CE1769A47A45F098A65CEC3089523543370DD37830A5B2D13,IsolateApps" />
  4.  
  5. </system.web>

而且负载均衡也设置了Class C的Session Affinity

后来发现这个问题即使本机访问也会出现。把应用程序池身份改为Admin后,问题同样。表明和权限无关。重新创建MachineKey,也没有变化。

这时需要关注代码。获取了页面代码做Review. 在Login页面的Page_Init里面, 看到ViewStateUserKey

  1. protected void Page_Init(object sender, EventArgs e)
  2. {
  3. this.ViewStateUserKey = this.Session.SessionID;
  4. }

表面上看这样的写法也没有什么问题。

在IE上启用了Fiddler (连接是SSL) 后,发现客户端的PostBack里面没有Cookie的信息。这就是问题出现的直接原因:

a. 在第一次访问Login页面时,用一个随机的SessionID A被嵌入了ViewState里面

b. 在PostBack时,由于没有Cookie传回来(ASP.NET SessionID缺省存放在Cookie里),服务器就判断道客户端没有SessionID, 于是又使用一个新的SessionID B做ViewStateUserKey. 这样,从ViewState里面解出的是上次的SessionID A, 和新的不匹配。错误就出现了。

可是客户端为什么不发送Cookie呢?

原来这个服务器第一次回复时,对客户端的HTTP Header里面根本没有Set-Cookie字段。

这是没有赋予Session 变量时ASP.NET的缺省行为 ( SessionID每次请求都会形成,但是未必会发送Set-Cookie 来让客户端保留这个SessioID,除非有赋予Session变量的行为)

于是解决这个问题的直接方法就是在这个Page_Init里面第一时间加一个语句:

  1. protected void Page_Init(object sender, EventArgs e)
  2. {
  3. this.ViewStateUserKey = this.Session.SessionID;
  4. session("forViewSate")="value"
  5.  
  6. }

这样服务器把SessionID在”Set-Cookie”里发送回去,客户端也可以用Cookie保留SessionID。问题就立刻解决了。

更多参考:

微软技术文章讨论如何处理” ”Validation of viewstate MAC failed”:

http://support.microsoft.com/kb/2915218

一个有趣的 ”Validation of viewstate MAC failed” 错误的发现和解决的更多相关文章

  1. ”Validation of viewstate MAC failed” 错误

    ”Validation of viewstate MAC failed” 错误 在ASP.NET里面,View State使用较为广泛.它作为一个隐藏字段,可以帮助服务端”记住“客户端的改变,这样客户 ...

  2. 转:Validation of viewstate MAC failed异常的原因及解决方法

    ViewState是一种机制,ASP.NET 使用这种机制来跟踪服务器控件状态值,否则这些值将不作为 HTTP 窗体的一部分而回传.也就是说在页面刷新或者回传的时候控件的值将被清空,我们在aspx.c ...

  3. Validation of viewstate MAC failed. 解决方法

    前段时间公司为了减轻服务器压力,对网页做了集群,分布在多台服务器,通过DNS轮回解析到各台服务器,结果页面只要打开停留到DNS解析到下一个地址,就会出现出下错误信息. Validation of vi ...

  4. Validation of viewstate MAC failed machinekey生成、使用方法

    前段时间公司为了减轻服务器压力,对网页做了集群,分布在多台服务器,通过DNS轮回解析到各台服务器,结果页面只要打开停留到DNS解析到下一个地址,就会出现出下错误信息. Validation of vi ...

  5. Validation of viewstate MAC failed 解决办法

    大部分人都说是在页里或web.config里加EnableEventValidation="false" EnableViewStateMac="false" ...

  6. 【问题收集·知识储备】Xcode只能选择My Mac,不能选择模拟器如何解决?

      网友问题:请问打开一个应用,只能选择My Mac,不能选择模拟器如何解决? 答案:             下面将问答过程记录如下:     CHENYILONG Blog 请问打开一个应用,只能 ...

  7. 关于安装teamviewer11出现verification of your teamviewer version failed错误处理

    关于安装teamviewer11出现verification of your teamviewer version failed错误处理 teamviewer 在ubuntu 中安装方法是: 去tea ...

  8. 【小贴士】关于transitionEnd/animate的一个有趣故事

    前言 在很久之前,我们项目有一个动画功能,功能本身很简单,便是典型的右进左出,并且带动画功能 以当时来说,虽然很简单,但是受限于框架本身的难度,就直接使用了CSS3的方式完成了功能 当时主要使用tra ...

  9. 一个有趣的SQL Server 层级汇总数据问题

        看SQL Server大V宋大侠的博客文章,发现了一个有趣的sql server层级汇总数据问题.          具体的问题如下:     parent_id emp_id emp_nam ...

随机推荐

  1. 母函数(Generating function)详解

    母函数(Generating function)详解 在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用 ...

  2. java并发操作

    项目中常用的java并发操作 一.java8新特性java并发流操作(结合纳姆达表达式) List<String> list = new ArrayList<>(); list ...

  3. - > 最大公约数(辗转相除法)和最小公倍数(公式法)

    最大公约数 #include<iostream> using namespace std; int a,b; int gcd(int x,int y){ return x==0?y:gcd ...

  4. Ubuntu 16.04安装设备管理器Hardinfo和lshw设备信息命令

    安装: sudo apt-get install hardinfo 启动: 实际上这些信息都可以通过lshw进行查看,参考:https://linux.die.net/man/1/lshw

  5. Ubuntu 16.04安装Grub Customizer替代Startup-manager(解决找不到menu.lst,GRUB配置简单介绍)

    关于GRUB的介绍: http://baike.baidu.com/item/GRUB http://blog.csdn.net/bytxl/article/details/9253713 menu. ...

  6. 12、Java并发性和多线程-Java同步块

    以下内容转自http://ifeve.com/synchronized-blocks/: Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免 ...

  7. what happens if we dont resolve or reject the promise

    https://stackoverflow.com/questions/36734900/what-happens-if-we-dont-resolve-or-reject-the-promise I ...

  8. 第6章 TCP/IP路由协议故障处理

    第6章 TCP/IP路由协议故障处理 一.缺省网关 当包的目的地址不在路由器的路由表中,如路由器配置了缺省网关,则转发到缺省网关,否则就丢弃. Show ip route :查看Cisco路由器的缺省 ...

  9. Python3基础(三) 运算符

    Python中的运算符大部分与C语言的类似,但也有很多不同的地方.这里就大概地罗列一下Python 3中的运算符. 一.算术运算符 运算符 描述 示例 x + y 加 10 + 20 = 30 x - ...

  10. LeetCode 884. Uncommon Words from Two Sentences (两句话中的不常见单词)

    题目标签:HashMap 题目给了我们两个句子,让我们找出不常见单词,只出现过一次的单词就是不常见单词. 把A 和 B 里的word 都存入 map,记录它们出现的次数.之后遍历map,把只出现过一次 ...