2012-09-09 7 views
10

Ho riscontrato seri problemi con @Html.AntiForgeryToken(). Ho un controller di registro con una vista creata per creare/registrare nuovi membri. Per questo motivo ho utilizzato uno @Html.AntiForgeryToken() senza utilizzare SALE nel mio modulo di invio principale. Ora vorrei convalidare il nome utente se è già presente nel database sull'evento sfocatura della mia casella di testo nome utente. Per questo ho scritto la validazione di un nuovo controller di nome 'convalida' e ho scritto un metodo con un sale di convalida costante:È possibile/giusto utilizzare più @ Html.AntiForgeryToken() in 2 forme diverse in una pagina?

[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); 

    } 

metodo sta lavorando bene. Avevo controllato con l'annotazione Get HTTP senza lo [ValidateAntiForgeryToken] e mi dava i risultati attesi.

Avevo cercato su google e controllato molte delle soluzioni fornite, nessuna di queste funzioni. Per il mio controller di convalida ho usato un altro modulo nella stessa pagina e ho usato un SALE nel token anti-contraffazione.

Esempio: primo token anti-contraffazione per la principale forma di conferma:

@using (Html.BeginForm ("Crea", "Registro")) { @ Html.AntiForgeryToken() @ Html.ValidationSummary (vero) ...}

secondo token anti-contraffazione:

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

e nel javascript ho usato questo

<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> 

Nel mio Firebug ho ottenuto questo:

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

come passato, ma nella sezione biscotto ho ottenuto un cookie diverso che passare una: Cookie reale:

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

Penso che questo sia perché ho usato 2 token anti-contraffazione in una pagina. Ma nella mia mente dovrei usare 2 perché il primo sta generando l'invio e il prossimo è necessario verificare la convalida. Tuttavia, questa è la mia ipotesi e penso di essermi sbagliato e per questo motivo ho bisogno di aiuto da voi ragazzi.

Qualcuno può spiegare i fatti che dovrei usare due anti-contraffazione o uno?

Grazie a tutti in anticipo ....

risposta

8

Infine 8 ore di lotta mi dà una soluzione.

Per prima cosa, sì, non c'è nulla di male nell'usare 2 segnalini anti-contraffazione nella pagina. E secondo non c'è bisogno di abbinare i cookie con il token che fornisce. Fornire token sarà sempre diverso e verrà verificato nel server.

Anti-contraffazione di token non funziona se usiamo [HttpGet] verbi di azione .. Perché nel processo di convalida di anti-contraffazione il token viene convalidato recuperando il valore Request.Form['__RequestVerificationToken'] dalla richiesta.ref: Steven Sanderson's blog: prevent cross...

Soluzione:

mio modifica regolatore:

[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); 
    } 

mio primo modulo nella stessa pagina:

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

    @Html.AntiForgeryToken(ApplicationEnvironment.SALT) 

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

Il secondo modulo nella stessa pagina:

**<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>** 

mio jQuery per risolvere questa 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); 
       } 
      }); 
     }); 
Problemi correlati