2009-09-13 2 views
16

Ho il seguente nella mia classe BasePage che tutte le mie pagine ASPX derivare da:Impostazione ViewStateUserKey mi dà un "Convalida di viewstate MAC non riuscita" errore

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

Ho anche un set machineKey in Web.config. Non penso che questo errore sia dovuto a una web farm perché questo accade anche sulla mia macchina di sviluppo.

Il mio host è ora aggiornato a .NET 3.5 SP1. Dopo questo aggiornamento, ogni volta che compilo con l'impostazione ViewStateUserKey, ottengo costantemente l'errore "Convalida MAC di viewstate non riuscito" su ogni postback.

Cosa sto facendo di sbagliato qui? Questa impostazione è ancora più necessaria con l'ultimo aggiornamento del framework?

risposta

14

OK - Im un anno di ritardo alla conversazione - ma come è questa la risposta corretta? Questo si applica solo nel caso di utenti autenticati e utilizzando lo ViewStateUserKey poiché il nome utente è molto più facile da indovinare rispetto a un ID di sessione ID GUID.

BTW se si desidera "correggere" il codice in alto, utilizzare l'ID sessione, tuttavia è necessario impostare una variabile di sessione in modo che l'ID di sessione smetta di cambiare ogni volta. Ex. Session["Anything"] = DateTime.Now

ViewStateUserKey = Session.SessionID; 

Questo, naturalmente, sta assumendo avete intenzione di usare le sessioni, altrimenti avete bisogno di qualche altro tasto da utilizzare come ad esempio il nome utente o di qualsiasi altro guid conservati in un cookie.

+1

Una nota aggiunta, a volte vedo il sessionid cambiare ogni volta fino a quando la sessione viene utilizzata, e altre volte il cookie di sessione viene inviato al client subito senza apparentemente utilizzare la sessione. Non sono sicuro al 100% perché ancora su questo, ma solo qualcosa che ho notato. –

+0

Questo è stato molto utile. Non sapevo che ASP non mantiene la sessione se nulla è stato salvato. – Reza

3

È possibile disattivare la codifica ViewState MAC con l'attributo EnableViewStateMac @Page?

+0

Sì, funziona se faccio questo. Preferisco rimuovere l'impostazione ViewStateUserKey se è inutile ... – Druid

+0

Bene, se sbarazzarsi di ViewStateUserKey funziona e non ne hai bisogno ... –

+1

Vero, ma sembra impostare questo aiuta contro un clic (CSRF) attacchi ... – Druid

4

ho riparato per ora modificando il codice a:

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

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

Impressionante, concediti un assegno per la risposta corretta. –

+1

@Druid Ho la stessa domanda qui oltre a mettere il codice sopra nell'evento Oninit della pagina di base .. ho bisogno di impostare viewstateuserkey in una qualsiasi delle pagine figlio .. Per favore, dimmi .... –

+0

@pratapk Finora come ricordo, non è necessario impostarlo su ogni pagina. – Druid

10

Ho cercato un po 'per trovare la causa definitiva del problema. Questo post di Microsoft ha davvero aiutato a spiegare tutte le diverse cause. http://support.microsoft.com/kb/2915218 Causa 4 è ciò che abbiamo atterrato su che è un invalido ViewStateUserKeyValue

Impostazione ViewStateUserKey a Session.SessionID o User.Identity.Name non ha funzionato per noi.

Abbiamo ricevuto intermittentemente l'errore di convalida a causa di quanto segue. Quando il pool di applicazioni viene ripristinato da IIS, la sessione viene rinnovata in effetti causando l'errore. Disconnettiamo la sessione all'accesso per evitare la fissazione della sessione, causando anche l'errore all'accesso.

Ciò che alla fine ha funzionato per noi era una soluzione basata su cookie, che ora viene fornita in 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

Potresti, per favore, elaborare di più? Non solo * link *. – Kamiccolo

+4

Spiegato perché le altre soluzioni non hanno funzionato per noi. E metti l'esempio del codice sul post. – Vincejtl

+0

Attualmente sto provando la tua soluzione e finora sembra che funzioni bene. – AFract

1

molto strano, anche io avuto problema simile per 3 giorni e ora ho risolto esso. 1. Avevo abilitato l'autenticazione forme e aveva ssl falsa

<forms defaultUrl="~/" loginUrl="~/Account/Login.aspx" requireSSL="false" timeout="2880" /> 
  1. ma nella mia httpCookies tag avevo requireSSL = true. Dal momento che nel Site.Master.cs usa i cookies per impostare il ViewStateUserKey, che stava avendo problemi

  2. quindi mi è stato sempre l'errore.

  3. Ho modificato questo in falso e riavviato l'app Web, ora è tutto a posto.