2012-09-09 22 views
10

He estado enfrentando un problema grave con @Html.AntiForgeryToken(). Tengo un controlador de registro que tenía una vista de creación para crear/registrar nuevos miembros. Por esa razón utilicé un @Html.AntiForgeryToken() sin usar ningún SALT en mi formulario principal de envío. Ahora me gustaría validar el nombre de usuario si ya existe en la base de datos en el evento borroso de mi cuadro de texto de nombre de usuario. Para esta validación escribí un nuevo controlador llamado 'validación' y escribió un método con una sal de validación constante:¿Es posible/correcto utilizar múltiples @ Html.AntiForgeryToken() en 2 formularios diferentes en una sola página?

[HttpPost] 
    [ValidateAntiForgeryToken(Salt = @ApplicationEnvironment.SALT)] 
    public ActionResult username(string log) { 
     try { 
      if (log == null || log.Length < 3) 
       return Json(log, JsonRequestBehavior.AllowGet); 

      var member = Membership.GetUser(log); 

      if (member == null) { 
       //string userPattern = @"^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$"; 
       string userPattern = "[A-Za-z][A-Za-z0-9._]{3,80}"; 
       if (Regex.IsMatch(log, userPattern)) 
        return Json(log, JsonRequestBehavior.AllowGet); 
      } 

     } catch (Exception ex) { 
      CustomErrorHandling.HandleErrorByEmail(ex, "Validate LogName()"); 
      return Json(log, JsonRequestBehavior.AllowGet); 
     } 
     //found e false 
     return Json(log, JsonRequestBehavior.AllowGet); 

    } 

Método está trabajando muy bien. Lo había comprobado con la anotación HTTP Get sin el [ValidateAntiForgeryToken] y me daba los resultados esperados.

Había buscado en Google y comprobado muchas de las soluciones dadas, ninguna de ellas funciona. Para mi controlador de validación utilicé otro formulario en la misma página y usé un SALT en el token Anti-falsificación.

Ejemplo: primer token anti-falsificación para el formulario principal presentar:

@using (Html.BeginForm ("Crear", "Register")) { @ Html.AntiForgeryToken() @ Html.ValidationSummary (verdadero) ...}

segundo marcador de anti-falsificación:

<form id="__AjaxAntiForgeryForm" action="#" method="post"> 
    @Html.AntiForgeryToken(SALT) 
</form> 

y en el javascript utilicé esta

<script type="text/javascript" defer="defer"> 
    $(function() { 
     AddAntiForgeryToken = function (data) { 
      data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val(); 
      return data; 
     }; 

     if ($("#LogName").length > 0) { 

      $("#LogName").blur(function() { 
       var user = $("#LogName").val(); 
       var logValidate = "/Validation/username/"; 
       //var URL = logValidate + user; 
       //var token = $('#validation input[name=__RequestVerificationToken]').val(); 
       data = AddAntiForgeryToken({ log: user }); 

       $.ajax({ 
        type: "POST", 
        dataType: "JSON", 
        url: logValidate, 
        data: data, 
        success: function (response) { 
         alert(response); 
        } 
       }); 

      }); 

     } 
    }); 
</script> 

En mi quemador, tengo esto:

log=admin&__RequestVerificationToken=NO8Kds6B2e8bexBjesKlwkSexamsruZc4HeTnFOlYL4Iu6ia%2FyH7qBJcgHusekA50D7TVvYj%2FqB4eZp4VDFlfA6GN5gRz7PB%2ByZ0AxtxW4nT0E%2FvmYwn7Fvo4GzS2ZAhsGLyQC098dfIJaWCSiPcc%2FfD00FqKxjvnqmxhXvnEx2Ye83LbfqA%2F4XTBX8getBeodwUQNkcNi6ZtAJQZ79ySg%3D%3D 

tal como fue aprobado pero en la sección de galletas Tengo una cookie distinta de pasar una: Cookies real:

ws5Dt2if6Hsah rW2nDly P3cW1smIdp1Vau 0TXOK1w0ctr0BCso/nbYu w9blq/QcrXxQLDLAlKBC3Tyhp5ECtK MxF4hhPpzoeByjROUG0NDJfCAlqVVwV5W6lw9ZFp/VBcQmwBCzBM/36UTBWmWn6pMM2bqnyoqXOK4aUZ4= 

Creo que esto se debe a que utilicé 2 tokens antifalsificación en una página. Pero en mi opinión debería usar 2 porque el primero genera para que se produzca el envío y el siguiente es necesario para verificar la validación. Sin embargo, esta es mi suposición y creo que estoy equivocado y por esta razón necesito ayuda de ustedes.

¿Puede alguien explicar los hechos que debo usar dos antifalsificación o uno?

Gracias a todos de antemano ....

Respuesta

8

Finalmente 8 horas de lucha me da una solución.

Lo primero es lo primero, sí, no hay daño al usar 2 tokens antifalsificación en la página. Y en segundo lugar, no es necesario hacer coincidir las cookies con el token que proporciona. Proporcionar token siempre será diferente y se verificará en el servidor.

Anti-falsificación símbolo no funciona si usamos verbos de acción [HttpGet] .. Debido a que en el proceso de validación de anti-falsificación de la ficha se valida mediante la recuperación del valor Request.Form['__RequestVerificationToken'] partir de la solicitud.ref: Steven Sanderson's blog: prevent cross...

Solución:

Mi modifica controlador:

[HttpPost] 

     [ValidateAntiForgeryToken(Salt = @ApplicationEnvironment.SALT)] 
//change the map route values to accept this parameters. 
     public ActionResult username(string id, string __RequestVerificationToken) { 
     string returnParam = __RequestVerificationToken; 

     try { 
      if (id == null || id.Length < 3) 
       return Json(returnParam, JsonRequestBehavior.AllowGet); 

      var member = Membership.GetUser(id); 

      if (member == null) { 
       //string userPattern = @"^([a-zA-Z])[a-zA-Z_-]*[\w_-]*[\S]$|^([a-zA-Z])[0-9_-]*[\S]$|^[a-zA-Z]*[\S]$"; 
       string userPattern = "[A-Za-z][A-Za-z0-9._]{3,80}"; 
       if (Regex.IsMatch(id, userPattern)) 
        return Json(returnParam, JsonRequestBehavior.AllowGet); 
      } 

     } catch (Exception ex) { 
      CustomErrorHandling.HandleErrorByEmail(ex, "Validate LogName()"); 
      return Json(returnParam, JsonRequestBehavior.AllowGet); 
     } 
     //found e false 
     return Json(returnParam, JsonRequestBehavior.AllowGet); 
    } 

Mi primer formulario en la misma página:

@using (Html.BeginForm("Create", "Register")) { 

    @Html.AntiForgeryToken(ApplicationEnvironment.SALT) 

    @Html.ValidationSummary(true) 
    .... 
} 

Mi segundo formulario en la misma página:

**<form id="validation"> 
    <!-- there is harm in using 2 anti-forgery tokens in one page--> 
    @Html.AntiForgeryToken(ApplicationEnvironment.SALT) 
    <input type="hidden" name="id" id="id" value="" /> 
</form>** 

Mi jQuery para resolver esta cosa:

$("#LogName").blur(function() { 
      var user = $("#LogName").val(); 
      var logValidate = "/Validation/username/"; 
      $("#validation #id").val(user); 
      **var form = $("#validation").serialize(); // a form is very important to verify anti-forgery token and data must be send in a form.** 

      var token = $('input[name=__RequestVerificationToken]').val(); 

      $.ajax({ 
       **type: "POST", //method must be POST to validate anti-forgery token or else it won't work.** 
       dataType: "JSON", 
       url: logValidate, 
       data: form, 
       success: function (response) { 
        alert(response); 
       } 
      }); 
     }); 
Cuestiones relacionadas