The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

當 ASP.NET 發生 Viewstate MAC 的驗證失敗 ( machineKey )

問題是這樣的,當 ASP.NET 因為網頁還沒全部下載完成時,使用者就按下網頁中的任意一個 PostBack 的按鈕或連結時,就會發生 Viewstate MAC 的驗證失敗 的錯誤訊息!

這問題實在很難除錯(DEBUG),我想很多人連發生的原因都不知道,主要的發生原因有兩種:

  1. 當網站採用 Web-farm 架構時,也就是一個網站採用負載平衡的架構,用多台 Web 主機同時提供服務時。

    因為 ASP.NET 預設會將 Viewstate 編碼加密,驗證資料的加密類型是 SHA1,驗證加密資料的金鑰(Key)預設是「自動產生」,所以每一台Web主機所產生的Key都不一樣,所以你採用多台主機同時提供服務時,就可能會遇到從第一台Web主機讀到的內容,做 PostBack 時可能會 PostBack 到第二台主機,但第二台主機看不懂第一台主機編碼過的 Viewstate,而導致「Viewstate MAC 的驗證失敗」的例外發生!

    這時你需要統一每一台主機的 machineKey 才能讓每一台的編碼加密的內容可以被正確驗證!建議您去 The Code Project 網站看這份 ASP.NET machineKey Generator 文件,上面有完整說明!

    也可以到我寫的 ASP.NET 2.0+ MachineKey Generator 機器金鑰生器產生出結果,然後放到 web.config<system.web> 區段下即可,如下範例:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        ...
      <system.web>
        ...
        <machineKey 
          validationKey="7626F91C8AEEEA2F126270ABB4B0DE36C2EF9BFD8D55D3F66D552276687FB85909C155EE6A26A3D617C588E6C42EEB8301098E98DAD6F29A20A6127EB6175F79"
          decryptionKey="245626CEA85BC34230D45467E607DBEF3862305E088EA2E5F8B8DA81F338B465"
          validation="SHA1" decryption="AES"
        />
        ...
      </system.web>
        ...
    </configuration>
    
  2. 因為網頁還沒全部下載完成,導致頁面的狀態不完整時就對伺服器發出 PostBack 要求,因為 ViewState 不完整,而導致 Viewstate 驗證失敗。

    這個問題只能將修改網站的 web.config 設定將 Viewstate 全部關閉才不會發生錯誤!如下:

    <pages enableEventValidation="false" viewStateEncryptionMode ="Never" />
    

參考資料