2010-02-28 24 views
8

La pagina che sto costruendo dipende fortemente da AJAX. Fondamentalmente, c'è solo una "pagina" e ogni trasferimento di dati viene gestito tramite AJAX. Dal momento che la cache troppo ottimistica sul lato del browser porta a strani problemi (dati non ricaricati), devo eseguire tutte le richieste (anche le letture) usando il POST - che forza una ricarica.Protezione CSRF in AJAX Richieste utilizzando MVC2

Ora voglio impedire la pagina contro CSRF. Con l'invio del modulo, utilizzando Html.AntiForgeryToken() funziona perfettamente, ma in richiesta AJAX, credo che dovrò aggiungere il token manualmente? C'è qualcosa fuori dalla scatola disponibile?

Il mio tentativo attuale assomiglia a questo:

Mi piacerebbe riutilizzare la magia esistente. Tuttavia, HtmlHelper.GetAntiForgeryTokenAndSetCookie è privato e non voglio incappare in MVC. L'altra opzione è quella di scrivere un'estensione come

public static string PlainAntiForgeryToken(this HtmlHelper helper) 
{ 
    // extract the actual field value from the hidden input 
    return helper.AntiForgeryToken().DoSomeHackyStringActions(); 
} 

che è un po 'hacky e lascia il problema più grande irrisolto: come verificare che gettone? L'implementazione di verifica predefinita è interna e codificata rispetto all'utilizzo dei campi modulo. Ho provato a scrivere un ValidateAntiForgeryTokenAttribute leggermente modificato, ma usa uno AntiForgeryDataSerializer che è privato e non volevo nemmeno copiarlo.

A questo punto sembra essere più facile trovare una soluzione di casa, ma questo è un codice realmente duplicato.

Qualche suggerimento su come farlo in modo intelligente? Mi manca qualcosa di completamente ovvio?

risposta

10

È possibile utilizzare il tradizionale Html.AntiForgeryToken() helper per generare un campo nascosto da qualche parte nella pagina (non necessariamente all'interno di un modulo) e includerlo lungo la richiesta AJAX:

var token = $('input[name=__RequestVerificationToken]').val(); 
$.post(
    '/SomeAction', { '__RequestVerificationToken': token }, 
    function() { 
     alert('Account Deleted.'); 
    } 
); 

per verificare che sul lato server:

[AcceptVerbs(HttpVerbs.Post)] 
[ValidateAntiForgeryToken] 
public ActionResult SomeAction() 
{ 
    return View(); 
} 

Se si dispone di più gettoni sulla tua pagina potrebbe essere necessario specificare quale includere. Mentre l'aiutante esistente genera i campi nascosti con gli stessi nomi è difficile fare un buon selettore di modo che tu possa metterli campate interne:

<span id="t1"><%= Html.AntiForgeryToken() %></span> 
<span id="t2"><%= Html.AntiForgeryToken() %></span> 

e quindi selezionare il corrispondente token:

var token = $('#t1 input[name=__RequestVerificationToken]').val(); 
+0

Brilliant! Funziona come un fascino! Non so che i campi inviati finirebbero nel 'Request.Form'. +1 per l'istruzione select molto accurata. Saluti! – mnemosyn

Problemi correlati