2009-09-13 172 views
16

在我BasePage類我有以下這我所有的ASPX頁面派生自:設置ViewStateUserKey給了我一個「驗證的視圖狀態MAC失敗」錯誤

protected override void OnInit(EventArgs e) 
{ 
    base.OnInit(e); 
    ViewStateUserKey = Session.SessionID; 
} 

我也有一個machineKeyWeb.config。我不認爲這個錯誤是因爲網絡農場,因爲這也發生在我的開發機器上。

我的主機現在已升級到.NET 3.5 SP1。此更新之後,每次我使用上面的ViewStateUserKey設置進行編譯時,我總是在每次回發中都收到「驗證視圖狀態MAC失敗」錯誤。

我在這裏做錯了什麼?隨着最新的框架更新,這個設置是否必要?

回答

14

行 - 林晚了一年的談話 - 但這是如何正確的答案?這僅適用於已通過身份驗證的用戶並使用ViewStateUserKey,因爲用戶名比會話ID GUID更容易猜測。

順便說一句,如果你想'修復'代碼頂部,使用會話ID,但是你必須設置一個會話變量,以便會話ID停止改變每次。防爆。 Session["Anything"] = DateTime.Now

ViewStateUserKey = Session.SessionID; 

當然,這是假設你要使用會話,否則你需要一些其他鍵使用,比如用戶名或任何其他GUID保存在cookie中。

+1

增加了一個註釋,有時我會看到sessionid每次都會改變,直到會話被使用,而其他時候會話cookie被立即發送到客戶端,而不會看似使用會話。我不是100%確定爲什麼在這個,但只是我注意到的東西。 –

+0

這非常有幫助。如果沒有保存在會話中,我不知道ASP會保留會話。 – Reza

3

您可以使用EnableViewStateMac @Page屬性關閉ViewState MAC編碼嗎?

+0

是的,如果我這樣做的工作。我寧願刪除ViewStateUserKey設置,如果它是沒用的... – Druid

+0

那麼,如果擺脫ViewStateUserKey的作品,你不需要它... –

+1

真的,但似乎設置這有助於防止一擊(CSRF )攻擊...... – Druid

4

我固定它現在的代碼更改爲:

protected override void OnInit(EventArgs e) 
{ 
    base.OnInit(e); 

    if (User.Identity.IsAuthenticated) 
     ViewStateUserKey = User.Identity.Name; 
} 
+1

真棒,給自己一個正確的答案檢查。 –

+1

@Druid除了將上述代碼放入基本頁的Oninit事件中,我在這裏也得到了同樣的問題。是否需要在任何子頁面中設置viewstateuserkey ..請您告訴我...... –

+0

@pratapk As far我記得,沒有必要在每一頁上都設置它。 – Druid

10

我搜索了很多,找到問題的確切原因。 微軟的這篇文章確實幫助解釋了所有不同的原因。 http://support.microsoft.com/kb/2915218 原因4是我們已經登陸上是無效的ViewStateUserKeyValue

設置ViewStateUserKey到Session.SessionID或User.Identity.Name我們沒有工作。

由於以下原因我們間歇性地得到了驗證錯誤。 當應用程序池被IIS重置時,會話將被更新以導致錯誤。 我們在登錄時刪除會話以避免會話固定,並導致登錄時出現錯誤。

終於爲我們工作的是基於cookie的解決方案,現在在VS2012中提供。

public partial class SiteMaster : MasterPage 
{ 
    private const string AntiXsrfTokenKey = "__AntiXsrfToken"; 
    private const string AntiXsrfUserNameKey = "__AntiXsrfUserName"; 
    private string _antiXsrfTokenValue; 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     //First, check for the existence of the Anti-XSS cookie 
     var requestCookie = Request.Cookies[AntiXsrfTokenKey]; 
     Guid requestCookieGuidValue; 

     //If the CSRF cookie is found, parse the token from the cookie. 
     //Then, set the global page variable and view state user 
     //key. The global variable will be used to validate that it matches in the view state form field in the Page.PreLoad 
     //method. 
     if (requestCookie != null 
     && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue)) 
     { 
      //Set the global token variable so the cookie value can be 
      //validated against the value in the view state form field in 
      //the Page.PreLoad method. 
      _antiXsrfTokenValue = requestCookie.Value; 

      //Set the view state user key, which will be validated by the 
      //framework during each request 
      Page.ViewStateUserKey = _antiXsrfTokenValue; 
     } 
     //If the CSRF cookie is not found, then this is a new session. 
     else 
     { 
      //Generate a new Anti-XSRF token 
      _antiXsrfTokenValue = Guid.NewGuid().ToString("N"); 

      //Set the view state user key, which will be validated by the 
      //framework during each request 
      Page.ViewStateUserKey = _antiXsrfTokenValue; 

      //Create the non-persistent CSRF cookie 
      var responseCookie = new HttpCookie(AntiXsrfTokenKey) 
      { 
       //Set the HttpOnly property to prevent the cookie from 
       //being accessed by client side script 
       HttpOnly = true, 

       //Add the Anti-XSRF token to the cookie value 
       Value = _antiXsrfTokenValue 
      }; 

      //If we are using SSL, the cookie should be set to secure to 
      //prevent it from being sent over HTTP connections 
      if (FormsAuthentication.RequireSSL && 
      Request.IsSecureConnection) 
      responseCookie.Secure = true; 

      //Add the CSRF cookie to the response 
      Response.Cookies.Set(responseCookie); 
     } 

      Page.PreLoad += master_Page_PreLoad; 
     } 

     protected void master_Page_PreLoad(object sender, EventArgs e) 
     { 
      //During the initial page load, add the Anti-XSRF token and user 
      //name to the ViewState 
      if (!IsPostBack) 
      { 
       //Set Anti-XSRF token 
       ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey; 

       //If a user name is assigned, set the user name 
       ViewState[AntiXsrfUserNameKey] = 
       Context.User.Identity.Name ?? String.Empty; 
      } 
      //During all subsequent post backs to the page, the token value from 
      //the cookie should be validated against the token in the view state 
      //form field. Additionally user name should be compared to the 
      //authenticated users name 
      else 
      { 
       //Validate the Anti-XSRF token 
       if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue 
       || (string)ViewState[AntiXsrfUserNameKey] != 
       (Context.User.Identity.Name ?? String.Empty)) 
      { 
      throw new InvalidOperationException("Validation of 
      Anti-XSRF token failed."); 
      } 
     } 
    } 
} 

Source

+0

可以請你詳細說明一下嗎?不僅*鏈接*。 – Kamiccolo

+4

解釋爲什麼其他解決方案不適合我們。並將代碼示例放在帖子中。 – Vincejtl

+0

我目前正在嘗試您的解決方案,目前看起來表現良好。 – AFract

1

很奇怪,我也曾經有過類似的問題,3天,現在我解決它。 1.我已經啓用表單認證和SSL了假

<forms defaultUrl="~/" loginUrl="~/Account/Login.aspx" requireSSL="false" timeout="2880" /> 
  • 但在我httpcookies標籤我有requireSSL =真。由於在Site.Master中。CS它使用cookies設置ViewStateUserKey,這是有問題

  • 所以我得到的錯誤。

  • 我將其修改爲錯誤並重新啓動的web應用程序,現在它的效果都很好。