2013-05-07 7 views
18

Ho un'app MVC 4 e ho problemi quando la sessione dei moduli scade e quindi l'utente prova a disconnettersi.Durante il tentativo di disconnessione, il token anti-contraffazione fornito era destinato all'utente "XXXX", ma l'utente corrente è ""

Es. Il timeout è impostato su 5 min. L'utente esegue il login. L'utente non esegue nulla per 10 minuti. L'utente fa clic sul collegamento LogOff. L'utente riceve errore: "Il token anti-contraffazione fornito era destinato all'utente" XXXX ", ma l'utente corrente è" "."

L'utente ha quindi dovuto sottoporsi a qualche ginnastica per aggirare il problema in modo da poter effettuare nuovamente il login, quindi effettuare nuovamente il logout (il logout viene utilizzato per chiudere il relativo cartellino del giorno).

Penso di capire perché questo accada ... ma non sono sicuro di come sistemarlo.

MODIFICA: Perché penso che questo stia accadendo è perché originariamente quando la pagina è caricata, il token AntiForgery viene generato per l'utente attualmente loggato. Ma poi quando la sessione scade e tentano di navigare verso la pagina di disconnessione, l'utente corrente è "" invece dell'utente reale. In quanto tale c'è una mancata corrispondenza e l'errore è reso.

+0

Puoi condividere la tua ipotesi per cui si verifica l'errore? – J0e3gan

+0

Un [post correlati] (http://stackoverflow.com/questions/14970102/anti-forgery-token-is-meant-for-user-but-the-current-user-is-username) sembra degno di essere preso in considerazione. – J0e3gan

+0

Aggiunta la mia ipotesi. Ho visto quel post a cui ti sei riferito e, sebbene possa essere correlato, non sono in grado di collegare i punti ... Non ho molta familiarità con questo aspetto di ASP.NET. –

risposta

22

In realtà si può gestire con IExceptionFilter, che reindirizza al /Account/Login

public class HandleAntiForgeryError : ActionFilterAttribute, IExceptionFilter 
{ 
    #region IExceptionFilter Members 

    public void OnException(ExceptionContext filterContext) 
    { 
     var exception = filterContext.Exception as HttpAntiForgeryException; 
     if (exception != null) 
     { 
      var routeValues = new RouteValueDictionary(); 
      routeValues["controller"] = "Account"; 
      routeValues["action"] = "Login"; 
      filterContext.Result = new RedirectToRouteResult(routeValues); 
      filterContext.ExceptionHandled = true; 
     } 
    } 

    #endregion 
} 

[HandleAntiForgeryError] 
[ValidateAntiForgeryToken] 
public ActionResult LogOff() 
{ 
} 

Inoltre è possibile utilizzare [HandleError(ExceptionType=typeof(HttpAntiForgeryException)...] ma richiede customErrors On.

+0

Eccellente! Proprio quello di cui avevo bisogno, grazie! –

+0

Non posso credere che questo non sia stato contrassegnato come risposta. Questa risposta è incredibile. –

+1

Per quello che vale, questo non funziona per me. Quando mi disconnetto, l'applicazione si interroga sullo stesso errore. Tuttavia, il tipo di eccezione è InvalidOperationException anziché HttpAntiforgeryException. Questo è molto generico, il che rende pericoloso gestirlo semplicemente:/ – Sinaesthetic

2

La risposta di @cem è stata davvero utile per me e ho aggiunto una piccola modifica per includere lo scenario delle chiamate ajax con antiforgerytoken e sessione scaduta.

public void OnException(ExceptionContext filterContext) 
{ 
    var exception = filterContext.Exception as HttpAntiForgeryException; 
    if (exception == null) return; 

    if (filterContext.HttpContext.Request.IsAjaxRequest()) 
    { 
     filterContext.HttpContext.Response.StatusCode = 403; 
     filterContext.ExceptionHandled = true; 
    } 
    else 
    { 
     var routeValues = new RouteValueDictionary 
     { 
      ["controller"] = "Account", 
      ["action"] = "Login" 
     }; 
     filterContext.Result = new RedirectToRouteResult(routeValues); 
     filterContext.ExceptionHandled = true; 
    } 
} 

... e sul lato client è possibile aggiungere un gestore di errore con la sessione globale per reindirizzare alla schermata di login ...

$.ajaxSetup({ 
    error: function (x) { 
     if (x.status === 403) { 
      window.location = "/Account/Login"; 
     } 
    } 
}); 
Problemi correlati