xsrf validateantiforgerytoken site net mvc forgery cross asp anti .net asp.net asp.net-mvc csrf

validateantiforgerytoken - ¿Cómo resuelvo una excepción AntiForgeryToken que ocurre después de un iisreset en mi aplicación ASP.Net MVC?



csrf web config (6)

Tengo problemas con AntiForgeryToken en ASP.Net MVC. Si realizo un iisreset en mi servidor web y un usuario continúa con su sesión, se los devuelve a una página de inicio de sesión. No es terrible, pero luego la ficha AntiForgery explota y la única forma de volver a empezar es soplar la cookie en el navegador.

Con la versión beta de la versión 1 solía salir mal al volver a leer la cookie, así que solía restregarla antes de pedir un token de validación, pero eso se solucionó cuando se lanzó.

Por ahora, creo que volveré a mi código que solucionó el problema beta, pero no puedo evitar pensar que me estoy perdiendo algo. ¿Hay una solución más simple, diablos debería dejar caer su ayudante y crear uno nuevo desde cero? Me da la sensación de que gran parte del problema es el hecho de que está tan atado a la antigua red de ASP.Net y está intentando convertirlo en algo para lo que en realidad no estaba diseñado.

Eché un vistazo al código fuente de ASP.Net MVC 2 RC y no parece que el código haya cambiado mucho, por lo que aunque no lo haya probado, no creo que haya ninguna respuesta.

Aquí está la parte relevante del rastro de la pila de la excepción.

Editar: Me acabo de dar cuenta de que no mencioné que esto solo está tratando de insertar el token en la solicitud GET. Esta no es la validación que se produce cuando se inicia un POST.

System.Web.Mvc.HttpAntiForgeryException: A required anti-forgery token was not supplied or was invalid. ---> System.Web.HttpException: Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster. ---> System.Web.UI.ViewStateException: Invalid viewstate. Client IP: 127.0.0.1 Port: 4991 User-Agent: scrubbed ViewState: scrubbed Referer: blah Path: /oursite/Account/Login ---> System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed. at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast) at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) at System.Security.Cryptography.CryptoStream.FlushFinalBlock() at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) --- End of inner exception stack trace --- --- End of inner exception stack trace --- at System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError) at System.Web.UI.ViewStateException.ThrowMacValidationError(Exception inner, String persistedState) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState) at System.Web.Mvc.AntiForgeryDataSerializer.Deserialize(String serializedToken) --- End of inner exception stack trace --- at System.Web.Mvc.AntiForgeryDataSerializer.Deserialize(String serializedToken) at System.Web.Mvc.HtmlHelper.GetAntiForgeryTokenAndSetCookie(String salt, String domain, String path) at System.Web.Mvc.HtmlHelper.AntiForgeryToken(String salt, String domain, String path)


Si realizo un iisreset en mi servidor web y un usuario continúa con su sesión, se los devuelve a una página de inicio de sesión.

No hay ninguna razón para enviar al usuario a la página de inicio de sesión. Si utiliza cookies para rastrear la información de autenticación y tiene una aplicación sin estado, el usuario debe permanecer autenticado incluso después de reiniciarse el servidor (por supuesto, si se realiza una solicitud durante el reinicio fallará).


En realidad, encontré esto para trabajar en mi acción de inicio de sesión:

public ActionResult LogOn() { formsAuthentication.SignOut(); Response.Cookies.Clear(); Session[SessionKeys.USER_SESSION_KEY] = null; Session.Clear(); Session.Abandon(); return View(); }

La parte importante fue: Response.Cookies.Clear ();


Por ahora, me he ido con una solución que friega la cookie si se lanza la excepción. Si la excepción se lanza nuevamente, dejaré que suceda como estaba.

No lo marcaré como ''la'' respuesta por ahora con la esperanza de que alguien tenga una mejor respuesta.

public static class MyAntiForgeryExtensions { // Methods public static string MyAntiForgeryToken(this HtmlHelper helper) { return MyAntiForgeryToken(helper, null); } public static string MyAntiForgeryToken(this HtmlHelper helper, string salt) { string fragment; string path = helper.ViewContext.HttpContext.Request.ApplicationPath; try { fragment = helper.AntiForgeryToken(salt, null, path); } catch (HttpAntiForgeryException) { // okay, scrub the cookie and have another go. string cookieName = GetAntiForgeryTokenName(path); helper.ViewContext.HttpContext.Request.Cookies.Remove(cookieName); fragment = helper.AntiForgeryToken(salt, null, path); } return fragment; } #region AntiForgeryData code that shouldn''t be sealed // Copied from AntiForgeryData since they aren''t accessible. internal static string GetAntiForgeryTokenName(string appPath) { if (String.IsNullOrEmpty(appPath)) { return "__RequestVerificationToken"; } else { return "__RequestVerificationToken_" + Base64EncodeForCookieName(appPath); } } private static string Base64EncodeForCookieName(string s) { byte[] rawBytes = Encoding.UTF8.GetBytes(s); string base64String = Convert.ToBase64String(rawBytes); // replace base64-specific characters with characters that are safe for a cookie name return base64String.Replace(''+'', ''.'').Replace(''/'', ''-'').Replace(''='', ''_''); } #endregion }


Puede agregar AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; en global.asax

protected void Application_Start() { AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; }


Si MachineKey está configurado en AutoGenerate, sus tokens de verificación, etc. no sobrevivirán al reinicio de una aplicación: ASP.NET generará una nueva clave cuando se inicie, y luego no podrá descifrar los tokens correctamente.

Si está viendo esto mucho, sugeriría:

  1. Configurar una MachineKey estática (debe poder hacer esto en el nivel de la aplicación), consulte "Cómo: Configurar una MachineKey" para obtener más información.
  2. Intente no realizar reinicios de IIS cuando el sitio se esté utilizando 1

1 La mejor forma de hacerlo es tener una aplicación con equilibrio de carga, que requerirá que establezca una MachineKey estática. Otra opción es eliminar el sitio colocando un archivo llamado app_offline.htm en la raíz del sitio, que desconectará el sitio y mostrará su mensaje; al menos, los usuarios esperarán que las cosas salgan mal.


Tuve este problema y para solucionar lo que debes hacer es agregar una clave de máquina explícita en tu configuración web ...

<machineKey validationKey="D82960E6B6E9B9029D4CAB2F597B5B4AF631E3C182670855D25FBDE1BFAFE19EFDE92ABBD1020FC1B2AE455D5B5F8D094325597CE1A7F8B15173407199C85A16" decryptionKey="577404C3A13F154908D7A5649EEC8D7C8A92C35A25A3EC078B426BB09D426A71" validation="SHA1" decryption="AES" />

asegurar que se coloque en web.config dentro de ...

<system.web>