2015-09-18 9 views
8

Desidero proteggere le azioni di accesso per Attributo antifrastro - So perché l'eccezione dell'argomento si verifica, tuttavia non riesco a trovare alcuna soluzione valida per questo.MVC5 AntiForgeryToken - come gestire "Il token anti-contraffazione fornito era destinato all'utente" ", ma l'utente corrente è" xxx "." eccezione?

Let dire che abbiamo le seguenti situazioni:

  1. E '8:00, gli utenti delle applicazioni vengono a lavorare, si siedono e iniziano il processo di login - in questo momento è molto possibile che alcuni utenti riceveranno lo stesso ValidationToken. Dopo che il primo è entrato, tutti gli altri vedranno l'eccezione di cui sopra (o qualche altra schermata di eccezione personalizzata) quando tentano di accedere.

  2. Alcuni registrazione dell'utente, poi premuto accidentalmente il "posteriore" bottone e ha tentato di accedere nuovamente - mentre questo è più improbabile, può succedere, e non voglio che gli utenti vedano le eccezioni quando lo fa .

Quindi la domanda è semplice - come prevenire le situazioni di cui sopra, o come gestirli in modo che gli utenti non noteranno nulla. Ho provato quanto segue:

  1. Impostazione dei AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application Start in Global.asax - è non risolvere il problema, ho ancora ottenere la stessa eccezione
  2. Impostazione del [OutputCache (NoStore = true, Durata = 0, VaryByParam = "Nessuno")] sul metodo con [ValidateAntiForgeryToken] attribuire - ancora una volta, senza fortuna ci

Proprio ora stavo pensando a validare manualmente il token in bascula, intercettare l'errore, e verifica se il tentativo è stato fatto da utente anonimo:

public ActionResult SomeAction() 
{ 
    try 
    { 
     AntiForgery.Validate(); 
    } 
    catch(HttpAntiForgeryException ex) 
    { 
     if(String.IsNullOrEmpty(HttpContext.User.Identity.Name)) 
     { 
      throw; 
     } 
    } 

    //Rest of action body here 
    //.. 
    //.. 
} 

È possibile che questo sembra impedire gli errori - Ma è sicuro?Quali alternative ci sono?

Grazie in anticipo.

Cordiali saluti.

EDIT:

La "soluzione" finale era quello di disattivare la convalida token form di login - ci può essere un modo migliore per gestire la cosa, ma sembra che tutte le soluzioni che ho trovato, erano brutti soluzioni simili alle mie proposte sopra.

Poiché non c'è modo di sapere quanto siano "sicure" quelle alternative (se sono sicure), abbiamo deciso di disabilitare la convalida del token al login.

+0

È possibile utilizzare gli script per disabilitare i doppi invii, http://stackoverflow.com/questions/2830542/prevent-double-submission-of-forms-in-jquery –

+0

Ciao, ho lo stesso problema quando l'utente preme il pulsante indietro sul browser. Con cosa sei finito? – VAAA

+0

@VAAA: Vedere la sezione EDIT della mia domanda - poiché solo il modulo di login ci ha dato questo problema, alla fine, abbiamo semplicemente disabilitato la convalida del token lì. Decidemmo che semplicemente non valeva la pena e, francamente, non riuscii a trovare una soluzione "pulita" - solo alcune brutte soluzioni (come quella che ho postato con il try-catch). – user2384366

risposta

7

Provare a impostare (in globale.cs):

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier; 

Questo aggiungerà l'identificativo nome per il token,

Per quanto riguarda il problema del doppio login tenta di utilizzare uno script per documentare la data e l'ora della originale Proporre di fermare una seconda presentare con lo stesso token.

// jQuery plugin to prevent double submission of forms 
jQuery.fn.preventDoubleSubmission = function() { 
    $(this).on('submit',function(e){ 
    var $form = $(this); 

    if ($form.data('submitted') === true) { 
     // Previously submitted - don't submit again 
     e.preventDefault(); 
    } else { 
     // Mark it so that the next submit can be ignored 
     $form.data('submitted', true); 
    } 
    }); 

    // Keep chainability 
    return this; 
}; 

Quindi sappiamo una cosa; gli utenti come il pulsante Indietro e hanno l'abitudine del doppio clic, questo è un grosso problema con AntiforgeryToken.

Ma a seconda di ciò che fa l'applicazione, ci sono modi per limitare la loro compulsione a farlo. La cosa più semplice è fare del tuo meglio per provare a far sì che il visitatore non senta il bisogno di "riavvolgere" la sua richiesta di alterarlo.

Assicurarsi che la messaggistica di errore modulo sia chiara e concisa per garantire l'utente sa cosa è sbagliato. Gli errori contestuali danno punti bonus.

Mantenere sempre lo stato modulo tra le richieste di modulo. Oltre alle password o ai numeri di carta di credito , non ci sono scuse, grazie agli assistenti di modulo MVC . @Html.LabelFor(x => x.FirstName)

Se i moduli sono distribuite su schede o div nascosti come quelli usati in quadri SPA come angolare o ember.js, essere intelligenti e mostra il layout del controller o forma che gli errori effettivamente originati dal in modulo di invio quando si visualizza l'errore. Non indirizzarli semplicemente a sul controller principale o sulla prima scheda.

“Cosa sta succedendo?” - Mantenere l'utilizzatore informato

Quando un AntiForgeryToken non convalida il vostro sito genererà un'eccezione di tipo System.Web.Mvc.HttpAntiForgeryException.

Se hai impostato correttamente hai attivato gli errori di amicizia e questo significa che la tua pagina di errore non mostrerà un'eccezione e mostrerà una bella pagina di errore che indica loro cosa succede.

È possibile rendere questo un po 'più semplice almeno dando all'utente una pagina più informativa mirata a queste eccezioni prendendo la HttpAntiForgeryException.

private void Application_Error(object sender, EventArgs e) 
{ 
    Exception ex = Server.GetLastError(); 

    if (ex is HttpAntiForgeryException) 
    { 
     Response.Clear(); 
     Server.ClearError(); //make sure you log the exception first 
     Response.Redirect("/error/antiforgery", true); 
    } 
} 

e la vostra vista /error/antiforgery può dire loro Mi dispiace che hanno cercato di presentare le stesse informazioni due volte

Un'altra idea è di registrare l'errore e tornare l'utente alla schermata di login:

Creare una classe HandleAntiforgeryTokenErrorAttribute che ignori il metodo OnException.

HandleAntiforgeryTokenErrorAttribute.cs:

public class HandleAntiforgeryTokenErrorAttribute : HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext filterContext) 
    { 
     filterContext.ExceptionHandled = true; 
     filterContext.Result = new RedirectToRouteResult(
      new RouteValueDictionary(new { action = "Login", controller = "Account" })); 
    } 
} 

filtro globale:

public class FilterConfig 
{ 
    public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new HandleErrorAttribute()); 
     filters.Add(new HandleAntiforgeryTokenErrorAttribute() 
      { ExceptionType = typeof(HttpAntiForgeryException) } 
     ); 
    } 
} 

Vorrei anche utilizzare alcuni strumenti per registrare tutte le vostre informazioni come di login è parte fondamentale della vostra applicazione

NLog per la registrazione generale e email su eccezioni di applicazioni critiche (incluse le eccezioni Web).

Elmah per filtraggio e posta elettronica di eccezioni Web.

MODIFICA: Inoltre, si consiglia di guardare un plugin jQuery chiamato SafeForm. Link

EDIT:

ho visto assegnare di dibattito su questo e viste di tutti sul tema hanno punti validi, come lo guardo è (Tratto da owasp.org)

Cross- CSRF (Site Request Forgery) è un attacco che costringe un utente finale a eseguire azioni indesiderate su un'applicazione Web in cui sono correntemente autenticato, attacchi CSRF specificamente indirizzati a modifiche di stato g richieste, non furto di dati. Il token anti-contraffazione è specifico per "chi è connesso". Quindi, una volta effettuato il login, poi tornare indietro, il vecchio token non è più valida

Ora ho anche utilizzare indirizzi IP autorizzati per il login di assegnare delle mie applicazioni con 2 autorizzazione fattore se gli utenti indirizzo IP cambia, quindi se In presenza di una richiesta di registrazione tra siti, l'utente non avrebbe trovato l'indirizzo IP e richiesto l'autorizzazione per 2 fattori. quasi come il modo in cui un router di sicurezza funzionerebbe. ma se vuoi tenerlo sulla tua pagina di accesso non vedo un problema finché hai le tue pagine di errore amichevoli che le persone non si arrabbieranno perché vedranno che hanno fatto qualcosa di sbagliato.

+0

Grazie per la risposta e scusa per la risposta tardiva - modifico leggermente la soluzione (utilizzo il campo di input nascosto per passare: "è stato inviato" valore) e ora la situazione di "pulsante indietro" sembra essere risolta, tuttavia la situazione di AD1 continua esiste, questo può essere simulato caricando, modulo di login in due diverse schede nel browser, posso chiaramente vedere che il cookie "___RequestverificationToken" è lo stesso per entrambe le schede, e quando invio invio lo stesso errore di prima. Mentre riesco a cogliere questa eccezione, non sono ancora in grado di farlo ... – user2384366

+0

Sinceramente La vera risposta a questo problema è semplicemente che non si dovrebbe usare un token anti-contraffazione sui moduli di accesso! È inutile "forgiare" essere un utente su un modulo di accesso - non sono ancora registrati e sono utenti anonimi fino a quando non hanno effettuato l'accesso!quindi, usando l'utente anonimo per creare il token di richiesta, il token anti-contraffazione dovrebbe essere usato sui moduli dopo che l'utente ha effettuato l'accesso, poiché le schede sullo stesso browser e computer non avranno nulla di diverso tra loro. –

+1

Per essere onesti, sono un po 'confuso al momento, perché sembrano esserci due punti di vista distinti sull'argomento, ad esempio qui: http://security.stackexchange.com/questions/2120/when-the -use-of-a-antiforgerytoken-is-not-required-needed Ho trovato una risposta piuttosto ampia con l'esempio, che afferma che il token anti contraffazione dovrebbe essere usato sul modulo di login ... d'altra parte ci sono molti altri post lo stato in caso contrario ... Aspetterò un po 'di più per altre possibili idee - ma se non arriva nulla, suppongo che farò come suggerisci tu e disabiliti la convalida del token :) – user2384366

Problemi correlati