2009-08-28 24 views
8

Attualmente sto sviluppando un'applicazione MVC in ASP.net. Sto usando AJAX.ActionLink per fornire un collegamento di eliminazione in un elenco di record, tuttavia questo è molto insicuro. Ho messo questo:ASP.net MVC AntiForgeryToken su AJAX

<AcceptVerbs(HttpVerbs.Post)> 

corso la funzione di fare la cancellazione, che ferma la funzione di essere chiamato semplicemente da un'URL. Tuttavia, l'altro buco di sicurezza che ancora esiste è che se dovessi fare una pagina di base HTML con questo contenuto:

<form action="http://foo.com/user/delete/260" method="post"> 
<input type="submit" /> 
</form> 

sarebbe comunque perfoming un post, ma da una posizione diversa.

È possibile utilizzare AntiForgeryToken con un ActionLink AJAX? Se è così, è un approccio sicuro? Ci sono più buchi di sicurezza che non ho realizzato?

risposta

2

Non conosco specificamente AJAX ActionLink, ma è possibile da una pagina WebForms pubblicare su un'azione MVC con gli attributi [AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken].

È possibile utilizzare la riflessione per ottenere i metodi MVC utilizzati per impostare il cookie e l'input del modulo di corrispondenza utilizzato per la convalida MVC.

Vedere questa risposta: Using an MVC HtmlHelper from a WebForm

9

Dai un'occhiata a questo blog post.

Diciamo che avete un metodo d'azione come questo:

[AcceptVerbs(HttpVerbs.Post), ValidateAntiForgeryToken] public ActionResult DeleteAccount(int accountId) { // delete stuff }

e vi invito tramite:

$.post('/home/DeleteAccount', { accountId: 1000 }, function() { alert('Account Deleted.'); });

Dal momento che il POST non include il AntiForgeryToken, fallirà.

Fortunatamente, non ci vuole molto cervello per risolvere questo problema. Tutto il componente client di AntiForgeryToken fa mettere il token in un campo nascosto . Quindi, devi solo inserire e includerlo in la tua chiamata AJAX.

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

$.post('/home/DeleteAccount', { accountId: 1000, '__RequestVerificationToken': token }, function() { alert('Account Deleted.'); });

Da notare che se si dispone di più forme sulla pagina con più AntiForgeryTokens, si dovrà specificare quale volete nella vostra selettore jQuery. Un altro punto è se si utilizza la funzione di jQuery serializeArray(), dovrete per aggiungere un po 'diverso:

var formData = $('#myForm').serializeArray(); var token = $('input[name=__RequestVerificationToken]').val(); formData.push({ name: '__RequestVerificationToken', value: token });

$.post('/home/DeleteAccount', formData, function() { alert('Account Deleted.'); });

Aggiornamento: Il collegamento è stato risolto.

+1

Quel link morto – Keith

+0

Non è necessario formData.push ({nome: '__RequestVerificationToken', valore: Token}); poiché serializeArray() restituirà tutti gli input nel modulo, che includono il campo nascosto __RequestVerificationToken. –

+0

Sì, questo è necessario per i post AJAX (utilizzando l'attuale MVC 4 e MS non invadente AJAX = jQuery) !!! –

0

Non ho mai utilizzato alcun helper Ajax, ma non vedo alcun motivo per cui non è possibile utilizzare un collegamento. Personalmente, utilizzerei un gestore di eventi onload per creare in modo discreto un collegamento dal modulo stesso e quindi rimuovere il modulo.

6

È possibile utilizzare AntiForgeryToken con Ajax.ActionLink, ma è necessario inserire manualmente l'AntiForgeryToken nell'intestazione della tua richiesta in questo modo:

function GetAntiForgeryToken(){ 
    var tokenWindow = window; 
    var tokenName = "__RequestVerificationToken"; 
    var tokenField = $(tokenWindow.document).find("input[type='hidden'][name='" +  tokenName + "']"); 
    if (tokenField.length == 0) {return null;} 
    else { 
     return { 
     name: tokenName, 
     value: tokenField.val() 
     }; 
    } 
}; 

Poi, possiamo usare $ .ajaxPrefilter per inserirlo nell'intestazione:

$.ajaxPrefilter(
    function (options, localOptions, jqXHR) { 
     var token = GetAntiForgeryToken(); 
     jqXHR.setRequestHeader(token.name, token.value); 
    } 
); 

ho scritto un post su di esso here. Spero che questo ti aiuti!

+0

Questo invia il token nell'intestazione, ma il filtro [ValidateAntiForgeryToken] lo richiede nei dati del modulo ... – iGanja

6

Uso AntiForgeryToken con Ajax.ActionLink

Oltre a jjwhite01 risposta; per inserire il token nei dati modulo, utilizzare option.data in Prefilter

$.ajaxPrefilter(
    function (options, localOptions, jqXHR) { 
     if (options.type !== "GET") { 
      var token = GetAntiForgeryToken(); 
      if (token !== null) { 
       if (options.data.indexOf("X-Requested-With") === -1) { 
        options.data = "X-Requested-With=XMLHttpRequest" + (options.data === "") ? "" : "&" + options.data; 
       } 
       options.data = options.data + "&" + token.name + '=' + token.value; 
      } 
     } 
    } 
); 
+1

Lo script ajax non invadente in MVC 4 include - options.data.push ({name: "X-Requested-With ", value:" XMLHttpRequest "}) - quindi il controllo e l'aggiunta per questo non sono più necessari – Brent