2010-02-28 11 views
8

La página que estoy construyendo depende en gran medida de AJAX. Básicamente, solo hay una "página" y cada transferencia de datos se maneja a través de AJAX. Como el almacenamiento en caché excesivamente optimista en el lado del navegador provoca problemas extraños (datos no cargados), tengo que realizar todas las solicitudes (también las lecturas) utilizando POST, lo que obliga a volver a cargar.Protección CSRF en solicitudes AJAX usando MVC2

Ahora quiero evitar la página contra CSRF. Con el envío de formularios, usar Html.AntiForgeryToken() funciona bien, pero en AJAX-request, ¿supongo que tendré que agregar el token manualmente? ¿Hay algo listo para usar disponible?

Mi intento actual se parece a esto:

Me encantaría volver a utilizar la magia existente. Sin embargo, HtmlHelper.GetAntiForgeryTokenAndSetCookie es privado y no quiero piratear en MVC. La otra opción es escribir una extensión como

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

que es un poco hacky y deja sin resolver el mayor problema: cómo verificar esa señal? La implementación de verificación predeterminada es interna y está codificada contra el uso de campos de formulario. Traté de escribir un ValidateAntiForgeryTokenAttribute ligeramente modificado, pero usa un AntiForgeryDataSerializer que es privado y realmente no quería copiar eso también.

En este punto, parece ser más fácil encontrar una solución de cosecha propia, pero realmente es un código duplicado.

¿Alguna sugerencia de cómo hacerlo de la manera más inteligente? ¿Me estoy perdiendo algo completamente obvio?

Respuesta

10

Se podría utilizar el Html.AntiForgeryToken() ayudante convencional para generar un campo oculto en algún lugar de la página (no necesariamente dentro de un formulario) e incluirlo a lo largo de la solicitud Ajax:

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

Para verificar que en el lado del servidor:

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

Si tiene varios tokens en su página, puede que necesite especificar cuál incluir. A medida que el ayudante existente genera los campos ocultos con los mismos nombres que es difícil hacer un buen selector de forma que los puede colocar luces en el interior:

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

y luego seleccione la ficha correspondiente:

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

Brilliant! ¡Funciona de maravilla! No sé si los campos publicados terminarían en 'Request.Form'. +1 para la declaración de selección muy clara. ¡Aclamaciones! – mnemosyn

Cuestiones relacionadas