2011-12-21 20 views
9

Im utilizzando MVC 3 e tutto è configurato correttamente da quello che posso vedere.Un token anti-contraffazione richiesto non è stato fornito o non è valido

Un utente Authenticates invia un modulo con il token AntiForgery e tutto funziona correttamente.

Vale a meno che l'utente non abbia lasciato il modulo da inviare aperto e entro quel tempo che il login utente è scaduto.

Quando l'utente invia il modulo poiché non è più autenticato, deve essere riportato alla pagina di accesso. (ciò accade alcune volte)

Invece l'eccezione "Un token anti-contraffazione richiesto non è stato fornito o non era valido." viene lanciato Immagino che venga gettato perché il token crittografato contiene alcuni dettagli dell'utente che non possono essere verificati poiché l'utente non è più autenticato.

L'eccezione è corretta ma non dovrebbe mai essere generata mentre la pagina dovrebbe tornare alla schermata di accesso poiché il vero problema è che l'utente si è allontanato da un modulo aperto e il tempo di accesso è scaduto.

Questo problema è difficile da replicare poiché non lo fa sempre.

Vedo che molte persone sembrano avere questo problema ma nessuna soluzione è imminente.

Si tratta di un problema all'interno di MVC stesso?

Le impostazioni della chiave del computer e tutto sono corretti, quindi non è questo il problema.

+0

La roba anti-contraffazione avviene in realtà in "System.Web.WebPages", non in MVC. Quindi dovresti cercare in quella fonte, piuttosto che in MVC. –

+0

Non sono sicuro che AntiForgeryToken abbia qualcosa a che fare con l'utente, in quanto può essere utilizzato indipendentemente dall'autorizzazione. Potrebbe essere legato al tempo. – stevethethread

risposta

2

Sto aggiungendo una risposta migliore qui perché questo è un dolore e mal risposto in tutto il web ho pensato di aggiungere le mie soluzioni attualmente lavoro.

Fondamentalmente (ignorando le varie opzioni) AntiForgeryToken funziona aggiungendo un cookie di sessione che viene poi letto quando il modulo viene pubblicato decorando un controller con l'attributo [ValidateAntiForgeryToken].

In primo luogo, prima di procedere alla correzione di qualsiasi cosa, come regola generale, fare sempre quanto segue.

  1. Nel web.config creare una macchinaKey come segue.

    <machineKey validationKey="YOUR_KEY" decryptionKey="YOUR_KEY" validation="SHA1" decryption="AES" />

    ** Nota SHA1 questo non è davvero questo è molto sicuro più ma un'altra discussione **

    Google <machineKey> Generator e configurare.

    http://msdn.microsoft.com/en-us/library/w8h3skw9%28v=vs.100%29.aspx

  2. Cambiare il nome del cookie di default da '__RequestVerificationToken' a quella che sarà non essere utilizzato da un'altra applicazione. (Io uso sempre un GUID).

    fare questo con AntiForgeryConfig.CookieName = "YOUR_NAME";

  3. Creare un nuovo attributo personalizzato.

Il motivo per questo errore sembra apparire per nessun motivo è che il cookie è valido solo per la vita di una sessione. Per vari motivi, ma soprattutto per il fatto che le persone lasciano le pagine aperte molto molto molto molto tempo la sessione scade. Poiché la sessione è scaduta, il cookie non è più valido.

Un altro problema è che se si dispone dell'attributo [Autorizza] sul postato sul controller, il flusso di elementi genererà HttpAntiForgeryException prima di verificare chi è autenticato. (nella maggior parte dell'autenticazione basata su cookie quando la sessione è scaduta l'utente non è più autenticato)

Il modo per risolvere questo è creare un attributo personalizzato [CustomValidateAntiForgeryToken].

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 
    public class CustomValidateAntiForgeryToken : FilterAttribute, IAuthorizationFilter { 

    public void OnAuthorization(AuthorizationContext filterContext) { 

     if (filterContext == null) { 
     throw new ArgumentNullException("filterContext"); 
     } 

     try { 
     AntiForgery.Validate(); 
     } 
     catch { 

     // Here do whatever is you wish 
     // you could just re throw the error or what ever. 

     // In this case I have redirected to a Signout 

     filterContext.Result = new RedirectToRouteResult( 
      new RouteValueDictionary( 
      new { 
       action  = "Sign_Out", 
       controller = "SOME_CONTROLLER", 
       area  = "" 
      } 
     ) 
     ); 

     } 

    } 

    } 

E, infine, se si cambia tutto questo in qualsiasi sistema attualmente in diretta assicurarsi che tutti si disconnette, si spegne il proprio browser, anche riavvia, se possibile, e cancella i cookie e cache. Si può ancora ricevere l'errore fino a quando non lo si fa per ogni utente anche dopo aver modificato il codice.

Ovviamente le persone hanno esigenze abbastanza diverse, ma si spera che questo dia abbastanza consigli per controllare questo problema molto comune e fastidioso.

Se qualcuno vede qualcosa che aiuti o possa essere aggiunto, per favore fallo.

1

Sull'azione inserire l'attributo [Authorize] sopra l'attributo [ValidateAntiForgeryToken]. Eseguono in ordine dall'alto verso il basso. Quindi, dovrebbe colpire l'autorizzazione e vedere che non sei più autenticato.

+0

Gli attributi non possono essere recuperati nell'ordine in cui li hai scritti, vero? –

+0

Ryand.Johnson che è già il caso, ma che non dovrebbe davvero causare il problema –

5

Il motivo è che in alcune grandi organizzazioni le persone lasciano le macchine accese senza riavvio e i browser aperti senza interruzioni per un tempo molto lungo. A volte persino settimane senza fine.

Se la chiave della macchina è stata aggiunta in un secondo momento o è stata modificata, le macchine che non sono state spente o che il browser è stato spento causano questo errore. Una volta riavviato il computer o spento il browser, l'errore si interromperà.

Nota: per interrompere questo errore è importante anche creare un codice macchina.

Google: macchina generatore di chiavi

+4

Non so perché questo è stato giù votato. Questo è esattamente ciò che stava causando il problema per noi e una volta che è stata aggiunta una chiave della macchina e tutte le macchine sono state riavviate, il problema non si verificava più. –

Problemi correlati