2012-03-26 15 views
6

tenemos un problema específico con el token anti falsificación en la página de inicio de sesión. Si el usuario inicia sesión con una sola ventana activa, todo funciona bien, pero si abre la página de inicio de sesión en dos ventanas diferentes e inicia sesión desde la ventana A (no se iniciará ningún problema), y vuelve a iniciar sesión desde la ventana B en esta ventana el usuario recibirá "No se proporcionó un token antifalsificación requerido o no fue válido".Mvc3 Multi pestañas token antiforgery

¿Hay alguna forma de evitar esto después de quitar la ficha antifalsificación de la acción vista/controlador? ¡Preferiríamos tener el token para seguridad adicional!

Esto es muy similar a esta pregunta sin embargo esto se pidió MVC2 MVC ValidateAntiForgeryToken multi-tabs problem

+0

Te he dejado otra respuesta - que debería haber respondido a mi propia pregunta! –

Respuesta

20

Este comportamiento en MVC3 o MVC4 está diseñado sin embargo, es muy poco amigable para el usuario como se explicó anteriormente, sin embargo, en producción, este problema debe resolverse correctamente y la aplicación debe manejar esta extraña situación. La solución para este problema es crear un filtro que se aplica a la publicación de inicio de sesión que verificará si el usuario está conectado y lo llevará a la página correcta, de lo contrario permanecerá en la página de inicio de sesión.

A continuación se muestra el código para el filtro de atributos

/// <summary> 
/// Handle Antiforgery token exception and redirect to customer area if the user is Authenticated 
/// </summary> 
public class RedirectOnError : HandleErrorAttribute 
{ 
    /// <summary> 
    /// Override the on exception method and check if the user is authenticated and redirect the user 
    /// to the customer service index otherwise continue with the base implamentation 
    /// </summary> 
    /// <param name="filterContext">Current Exception Context of the request</param> 
    public override void OnException(ExceptionContext filterContext) 
    { 
     if (filterContext.Exception is HttpAntiForgeryException && filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      // Set response code back to normal 
      filterContext.HttpContext.Response.StatusCode = 200; 

      // Handle the exception 
      filterContext.ExceptionHandled = true; 

      UrlHelper urlH = new UrlHelper(filterContext.HttpContext.Request.RequestContext); 

      // Create a new request context 
      RequestContext rc = new RequestContext(filterContext.HttpContext, filterContext.RouteData); 

      // Create a new return url 
      string url = RouteTable.Routes.GetVirtualPath(rc, new RouteValueDictionary(new { Controller = "CustomerArea", action = "Index" })).VirtualPath; 

      // Check if there is a request url 
      if (filterContext.HttpContext.Request.Params["ReturnUrl"] != null && urlH.IsLocalUrl(filterContext.HttpContext.Request.Params["ReturnUrl"])) 
      { 
       url = filterContext.HttpContext.Request.Params["ReturnUrl"]; 
      } 

      // Redirect the user back to the customer service index page 
      filterContext.HttpContext.Response.Redirect(url, true); 
     } 
     else 
     { 
      // Continue to the base 
      base.OnException(filterContext); 
     } 
    } 
} 

Este es el ejemplo de uso

 [HttpPost] 
     **[RedirectOnError]** 
     [ValidateAntiForgeryToken] 
     public ActionResult LogOn(LogOnViewModel model, UserSessionState session, string returnUrl) 
     { 
     ..... 
     } 
+0

No entiendo lo que sucede si el usuario no está conectado ... porque permanecer en la página de registro podría dar como resultado la excepción nuevamente. – ilans

+2

En respuesta a IlanS - código si (filterContext.Exception se HttpAntiForgeryException && filterContext.HttpContext.User.Identity.IsAuthenticated) sólo se aplicará la redirección si el usuario está conectado, de lo contrario la excepción habitual para un usuario no autenticado es arrojado. – MORCHARD

+0

¡Gran solución! –

4

Una vez que se conecte, todas las fichas anteriores no son válidas. Así es como se supone que debe funcionar. Naz se acerca a la respuesta correcta, excepto que el token en la cookie no almacena el nombre de usuario. Solo el token en la forma lo hace. Es precisamente por este motivo: si un usuario inicia sesión, todos los tokens forma existentes deberían invalidarse, pero invalidar la cookie sería demasiado problemático y poco amigable para el usuario.