asp.net mvc - net - Problema de token de validación de solicitud de inicio de sesión
login entity framework c# mvc (4)
Acabo de probar este patrón en ASafaWeb con el mismo resultado (usa la misma implementación predeterminada). Esto es lo que creo que está sucediendo
- Ambos formularios de inicio de sesión se cargan con la misma cookie __RequestVerificationToken (es la misma que se estableció en el mismo DOM) y el mismo campo oculto __RequestVerificationToken. Estos tokens están codificados por un usuario anónimo.
- Formulario de inicio de sesión A publicaciones con los tokens anteriores, los valida y luego devuelve una cookie de autenticación que ahora está en el navegador DOM
- El formulario de inicio de sesión B publica también los tokens anteriores, pero ahora también está publicando con el conjunto de cookies de autenticación desde el formulario de inicio de sesión A también.
El problema es que el token no valida en el paso 3 porque está codificado para un usuario anónimo, pero lo pasa un usuario autenticado en la solicitud. Es por eso que está viendo el error: el token antifalsificación proporcionado estaba destinado para el usuario "", pero el usuario actual es "admin"
Solo tiene este problema porque el formulario B se envió antes que el formulario A publicado, por lo tanto, el formulario B espera que lo publique un usuario anónimo.
¿Es un problema eliminarlo de un formulario que, por definición, será utilizado por usuarios no autenticados?
El riesgo subyacente predominante contra el que se protegen las fichas antifalsificación es CSRF, que normalmente aprovecha los usuarios autenticados debido a que cualquier solicitud de engaño para su navegador será automáticamente acompañada de una cookie de autenticación, por lo que la acción se realizará en su favor. Este riesgo no existe en el formulario de inicio de sesión porque generalmente el usuario no está autenticado y el peor caso de CSRF aquí es que un inicio de sesión se falsifica y luego falla; ¡no estás transfiriendo exactamente dinero en nombre del usuario!
Sin embargo, existen otras ventajas para el token anti falsificación: por ejemplo, evita que los ataques de fuerza bruta realmente ejecuten el método y golpeen el DB. Debe decidir si está menos preocupado por esto y más preocupado por el escenario que está encontrando en su pregunta. O bien eso o necesita desplegarse en la canalización de solicitudes en algún lugar y tomar medidas si una cookie de autenticación ya está presente en la solicitud antes de que ocurra la validación antifalsificación.
Sin embargo, francamente, no estoy seguro de ver el problema; Para reproducir este problema, el usuario debe tener múltiples formularios de inicio de sesión abiertos al mismo tiempo e intentar ingresar a cada uno de ellos de forma sucesiva. ¿Esto realmente va a suceder lo suficiente como para preocuparse? Y cuando sucede, ¿realmente importa que el segundo inicio de sesión devuelva una página de error personalizada (que por supuesto harías en producción)? En mi humilde opinión, abandone el comportamiento predeterminado.
He estado revisando los registros de errores de un proyecto de desarrollo y encontré el siguiente error (el nombre cambió para proteger al culpable inocente) -
El token antifalsificación proporcionado estaba destinado para el usuario "", pero el usuario actual es "admin".
Este no fue un tema especialmente difícil de reproducir-
- Abra la aplicación en la página de inicio de sesión
- Abra una segunda ventana o pestaña en el mismo navegador en la misma computadora que la página de inicio de sesión antes de iniciar sesión
- Inicie sesión en la primera ventana (o en segundo lugar, el orden no importa)
- Intentar iniciar sesión en la ventana de inicio de sesión restante
El seguimiento de la pila es-
System.Web.Mvc.HttpAntiForgeryException (0x80004005): el token antifalsificación proporcionado está destinado para el usuario "", pero el usuario actual es "admin". en System.Web.Helpers.AntiXsrf.TokenValidator.ValidateTokens (HttpContextBase httpContext, identidad de Identity, AntiForgeryToken sessionToken, AntiForgeryToken fieldToken) en System.Web.Helpers.AntiXsrf.AntiForgeryWorker.Validate (HttpContextBase httpContext) en System.Web.Helpers.AntiForgery. Validate () en System.Web.Mvc.ValidateAntiForgeryTokenAttribute.OnAuthorization (AuthorizationContext filterContext) en System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters (ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor) en System.Web.Mvc.Async.AsyncControllerActionInvoker. <> c__DisplayClass25.b__1e (AsyncCallback asyncCallback, Object asyncState)
La firma del método de inicio de sesión es-
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
...
}
Esto es exactamente lo mismo que la firma para el método en un proyecto con plantilla de "Aplicación Web ASP.NET MVC 4" de Internet, que indica que Microsoft consideró que ValidateAntiForgeryToken era necesario / mejor práctica, o simplemente agregó el atributo aquí porque se utilizó en todos lados.
Obviamente no hay nada que pueda hacer para manejar el problema dentro de este método, ya que no se alcanza, el ValidateAntiForgeryToken es un filtro de solicitud previa y está bloqueando la solicitud antes de que llegue al controlador.
Podría verificar si el usuario está autenticado mediante Ajax antes de enviar el formulario e intentar redirigirlo si es así, o simplemente eliminar el atributo.
La pregunta es: entiendo que el token está diseñado para evitar solicitudes de otro sitio (CSRF) cuando el usuario ya está autenticado en su sitio, por lo que es un problema eliminarlo de un formulario que, por definición, se utilizará. por usuarios no autenticados ?
Presumiblemente, el atributo en esta instancia está diseñado para mitigar a los actores malintencionados que proporcionan formularios de inicio de sesión falsos para su aplicación (aunque para el momento en que se lanza la excepción, presumiblemente el usuario ya ha ingresado sus datos que se habrán grabado, pero podría alertarles Está Mal). De lo contrario, el envío de credenciales incorrectas al formulario desde un sitio externo dará como resultado exactamente el mismo resultado que en el sitio en sí mismo. No confío en la validación / saneamiento del cliente para limpiar entradas potencialmente inseguras.
¿Han encontrado otros desarrolladores este problema (o tenemos usuarios inusualmente creativos)? En caso afirmativo, ¿cómo lo resolvió / mitigó?
Actualización: Este problema todavía existe en MVC5, de manera totalmente intencional, ahora con el mensaje de error "El token antifalsificación proporcionado se diseñó para un usuario diferente basado en notificaciones que el usuario actual". cuando se usa la plantilla predeterminada y los proveedores de Identidad. Hay una pregunta relevante y una respuesta interesante de Microsoft Developer Evangelist y del autor de PluralSight de Troy, Adam Tuliper, en la ficha Anti falsificación en la página de inicio de sesión, que recomienda simplemente eliminar el token.
El código de validación que se ejecuta en contra de AntiForgeryToken también verifica que sus credenciales de usuario no hayan cambiado; estas también están encriptadas en la cookie. Esto significa que si ingresó o salió en una ventana emergente u otra pestaña del navegador, su envío de formularios fallará con la siguiente excepción:
System.Web.Mvc.HttpAntiForgeryException (0x80004005):
The provided anti-forgery token was meant for user "", but the current user is "SomeOne".
Puede desactivarlo poniendo AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; en el método Application_Start dentro del archivo Global.asax .
Cuando un AntiForgeryToken no valida su sitio web lanzará una Excepción de tipo System.Web.Mvc.HttpAntiForgeryException . Puede hacer que esto sea un poco más fácil al brindarle al usuario una página más informativa dirigida a estas excepciones al capturar 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);
}
}
Está bien, por favor corrígeme si mi suposición es incorrecta.
Cuando se lanza esta excepción, ¿preferiría dejar que el usuario continúe mientras que también puede mostrar un mensaje / advertencia relevante? Porque cuando se lanza esta excepción, ya podemos saber si el usuario actual está autenticado, tenemos acceso a la solicitud.
Entonces, ¿por qué esto no sería aceptable?
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
...
}
/// <summary>
/// Handle HttpAntiForgeryException and redirect if user is already authenticated
/// </summary>
/// <param name="filterContext"></param>
/// <remarks>
/// See: http://.com/questions/19096723/login-request-validation-token-issue
/// </remarks>
protected override void OnException(ExceptionContext filterContext)
{
base.OnException(filterContext);
var action = filterContext.RequestContext.RouteData.Values["action"] as string;
var controller = filterContext.RequestContext.RouteData.Values["controller"] as string;
if ((filterContext.Exception is HttpAntiForgeryException) &&
action == "Login" &&
controller == "MyController" &&
filterContext.RequestContext.HttpContext.User != null &&
filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
{
LogManager.GetCurrentClassLogger().Warn(
"Handled AntiForgery exception because user is already Authenticated: " +
filterContext.Exception.Message, filterContext.Exception);
filterContext.ExceptionHandled = true;
// redirect/show error/whatever?
filterContext.Result = new RedirectResult("/warning");
}
}
¿Me estoy perdiendo algo obvio aquí? Eliminaré esta respuesta si tiene alguna implicación que no estoy viendo.
Tuve el mismo problema, lo resolví agregando machineKey a system.web>
<machineKey validationKey="your machine key numbers"
decryptionKey="Your description key nuumbers" validation="SHA1" decryption="AES" />
Aquí hay un sitio que genera Machnie Keys único http://www.developerfusion.com/tools/generatemachinekey/
Funciona muy bien, entiendo que Anti Forgery puede no ser necesario en una página de inicio de sesión, pero si alguien está decidido a piratear tu sitio, es reconfortante saber que [ValidateAntiForgeryToken] está ahí para frustrarlos.