asp.net-mvc - route - tag helpers asp net core
Solución de problemas de token antifalsificación (11)
Tengo una publicación de formulario que constantemente me da un error de token anti falsificación.
Aquí está mi formulario:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.EditorFor(m => m.Email)
@Html.EditorFor(m => m.Birthday)
<p>
<input type="submit" id="Go" value="Go" />
</p>
}
Aquí está mi método de acción:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Join(JoinViewModel model)
{
//a bunch of stuff here but it doesn''t matter because it''s not making it here
}
Aquí está la máquina clave en web.config:
<system.web>
<machineKey validationKey="mykey" decryptionKey="myotherkey" validation="SHA1" decryption="AES" />
</system.web>
Y aquí está el error que recibo:
A required anti-forgery token was not supplied or was invalid.
He leído que cambiar usuarios en HttpContext invalidará el token, pero esto no está sucediendo aquí. El HttpGet en mi acción de unión solo devuelve la vista:
[HttpGet]
public ActionResult Join()
{
return this.View();
}
Entonces no estoy seguro de lo que está pasando. He buscado, y todo parece indicar que es la máquina el cambio de tecla (ciclos de la aplicación) o el usuario / sesión cambia.
¿Qué más podría estar pasando? ¿Cómo puedo solucionar esto?
¿Estás en un servidor o una granja web? Si es un servidor único, comente el elemento machineKey en su web.config y vuelva a intentarlo como punto de partida base. ¿Cualquier cambio? Además, ¿puede pensar en alguna razón por la que sus cookies se eliminarán o caducarán? También se requiere que esto funcione correctamente.
Acabo de experimentar un problema por el que se @Html.AntiForgeryToken()
dos veces para que el token Anti-forger se estropeara en la carga útil de HTTP Post.
Acabo de tener un problema similar. Tengo:
The required anti-forgery form field "__RequestVerificationToken" is not present.
Lo que es de interés es que probé a depurarlo y vi el token en ambos lugares que esperaba encontrarlo en el controlador
var formField = HttpContext.Request.Params["__RequestVerificationToken"];
var cookie = System.Web.HttpContext.Current.Request.Cookies["__RequestVerificationToken"].Value;
En realidad, debería haber estado buscando aquí:
var formField = HttpContext.Request.Form["__RequestVerificationToken"];
Como Params contiene más que solo los campos de formulario, contiene QueryString, Form, Cookies y ServerVariables.
¡Una vez que el arenque rojo estuvo fuera del camino, descubrí que AntiForgeryToken estaba en la forma incorrecta!
AntiForgeryToken también verifica que las credenciales de usuario registradas no hayan cambiado, sino que también están encriptadas en la cookie. Puede desactivar esto configurando AntiForgeryConfig.SuppressIdentityHeuristicChecks = true
en el archivo global.asax.cs.
Debe evitar el envío de formularios dobles. Impedí este tipo de problema usando un código como este:
$(''#loginForm'').on(''submit'',function(e){
var $form = $(this);
if (!$form.data(''submitted'') && $form.valid()) {
// mark it so that the next submit can be ignored
$form.data(''submitted'', true);
return;
}
// form is invalid or previously submitted - skip submit
e.preventDefault();
});
o
$(''#loginForm'').submit(function () {
$(this).find('':submit'').attr(''disabled'', ''disabled'');
});
Después de la ayuda de Adam, obtuve la fuente MVC agregada a mi proyecto, y pude ver que hay muchos casos que producen el mismo error.
Aquí está el método usado para validar el token anti falsificación:
public void Validate(HttpContextBase context, string salt) {
Debug.Assert(context != null);
string fieldName = AntiForgeryData.GetAntiForgeryTokenName(null);
string cookieName = AntiForgeryData.GetAntiForgeryTokenName(context.Request.ApplicationPath);
HttpCookie cookie = context.Request.Cookies[cookieName];
if (cookie == null || String.IsNullOrEmpty(cookie.Value)) {
// error: cookie token is missing
throw CreateValidationException();
}
AntiForgeryData cookieToken = Serializer.Deserialize(cookie.Value);
string formValue = context.Request.Form[fieldName];
if (String.IsNullOrEmpty(formValue)) {
// error: form token is missing
throw CreateValidationException();
}
AntiForgeryData formToken = Serializer.Deserialize(formValue);
if (!String.Equals(cookieToken.Value, formToken.Value, StringComparison.Ordinal)) {
// error: form token does not match cookie token
throw CreateValidationException();
}
string currentUsername = AntiForgeryData.GetUsername(context.User);
if (!String.Equals(formToken.Username, currentUsername, StringComparison.OrdinalIgnoreCase)) {
// error: form token is not valid for this user
// (don''t care about cookie token)
throw CreateValidationException();
}
if (!String.Equals(salt ?? String.Empty, formToken.Salt, StringComparison.Ordinal)) {
// error: custom validation failed
throw CreateValidationException();
}
}
Mi problema era esa condición en la que compara el nombre de usuario de Identity con el nombre de usuario del token de formulario. En mi caso, no tenía el nombre de usuario configurado (uno era nulo, el otro era una cadena vacía).
Aunque dudo que muchos se encuentren con este mismo escenario, espero que a otros les resulte útil ver las condiciones subyacentes que se controlan.
El registrador de errores html no es la línea correcta.
debe verificar que todo el valor de carga en la página no sea nulo.
Es necesario verificar el formulario si es válido, antes de desactivar el botón de enviar.
<script type="text/javascript">
//prevent double form submission
$(''form'', ''#loginForm'').submit(function () {
if ($(this).valid()) {
$(this).find('':submit'').attr(''disabled'', ''disabled'');
}
});
No sé si quiere decir que puede obtener el error a pedido, o lo está viendo en sus registros, pero en cualquier caso, esta es una manera de garantizar un error de token antiforgery.
Espera ...
- Asegúrate de haber cerrado la sesión, luego ingresa tu nombre de usuario
- Haga doble clic en el botón de inicio de sesión
- Obtendrás :
El token antifalsificación proporcionado está destinado para el usuario "", pero el usuario actual es "[email protected]".
(Por ahora voy a suponer que este mensaje de error exacto cambió en MVC4 y que este es esencialmente el mismo mensaje que está recibiendo).
Hay mucha gente por ahí que todavía hace doble clic en todo, ¡esto es malo! Me acabo de dar cuenta de esto después de despertar, así que cómo pasó esto en las pruebas realmente no lo sé. Ni siquiera tiene que hacer doble clic: tengo este error yo mismo cuando hago clic por segunda vez si el botón no responde.
Acabo de eliminar el atributo de validación. Mi sitio siempre es SSL y no estoy demasiado preocupado por el riesgo. Solo necesito que funcione ahora mismo. Otra solución sería deshabilitar el botón con javascript.
Esto se puede duplicar en la plantilla de instalación inicial de MVC4.
Otra posible cosa para comprobar que ha causado este error para mí: tenía dos @Html.AntiForgeryToken()
en uno de mis formularios.
Una vez que se eliminó, el problema desapareció.
También tuve este mismo problema cuando tuve que migrar mi aplicación a una máquina nueva. No pude entender por qué este error se manifestó repentinamente pero sentí que tenía algo que ver con la migración, así que comencé a investigar el registro de la base de datos a través de aspnet_reqsql, cuando esto se eliminó me di cuenta de que tenía que ver con el registro de la aplicación y efectivamente encontré la respuesta en un lugar similar. También en mi viaje descubrí que hay 2 formas de resolver esto.
ASP.NET genera automáticamente una clave de criptografía para cada aplicación y almacena la clave en la sección de registro de HKCU. Cuando se migra la aplicación o se accede a ella en una granja de servidores, estas claves no coinciden, por lo que el método uno es agregar una clave de máquina única a web.config. La clave del equipo se puede generar desde la consola de administración de IIS y agregar a la sección de su web.config
<MachineKey validationKey = "DEBE0EEF2A779A4CAAC54EA51B9ACCDED506DA2A4BEBA88FA23AD8E7399C4A8B93A006ACC1D7FEAEE56A5571B5AB6D74819CFADB522FEEB101B4D0F97F4E91" decryptionKey = "7B1EF067E9C561EC2F4695578295EDD5EC454F0F61DBFDDADC2900B01A53D4" validación = descifrado "SHA1" = "AES" />
El segundo método es otorgar acceso al registro de HKCU para el proceso de trabajo a través de la appPool utilizando AspNet_RegIIS y el conmutador -ga o para todas las aplicaciones que usan -i
aspnet_regiis -ga "IIS APPPOOL / app-pool-name"
Cualquiera que sea el método que elija debería resolver este problema, pero en mi opinión la forma más sólida para futuras migraciones y cambios en el servidor será la clave única en el archivo web.config, teniendo en cuenta que esto hará que la aplicación anule el registro HKCU. colmena y mantiene su aplicación ejecutándose.