He implementado en mi aplicación la mitigación de los ataques CSRF siguiendo las informaciones que he leído en alguna publicación de blog en Internet. En particular, estas publicaciones han sido el motor de mi implementación
- Mejores prácticas para ASP.NET MVC del equipo de contenido de desarrolladores de herramientas web y ASP.NET
- Anatomía de un ataque de falsificación de solicitud de sitios cruzados del blog de Phil Haack
- AntiForgeryToken en el Framework ASP.NET MVC - Html.AntiForgeryToken y ValidateAntiForgeryToken Attribute del blog de David Hayden
Básicamente, esos artículos y recomendaciones dicen que para evitar el ataque CSRF cualquiera debería implementar el siguiente código:
1) Agregue el [ValidateAntiForgeryToken]
en cada acción que acepte el verbo Http POST
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SomeAction( SomeModel model ) {
}
2) Agregue el <%= Html.AntiForgeryToken() %>
ayudante dentro de los formularios que envían datos al servidor
<div style="text-align:right; padding: 8px;">
<%= Html.AntiForgeryToken() %>
<input type="submit" id="btnSave" value="Save" />
</div>
De todos modos, en algunas partes de mi aplicación, estoy haciendo Ajax POST con jQuery al servidor sin tener ningún formulario. Esto sucede, por ejemplo, cuando dejo que el usuario haga clic en una imagen para realizar una acción específica.
Supongamos que tengo una tabla con una lista de actividades. Tengo una imagen en una columna de la tabla que dice "Marcar actividad como completada" y cuando el usuario hace clic en esa actividad, estoy haciendo la POST de Ajax como en la siguiente muestra:
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {},
success: function (response) {
// ....
}
});
});
¿Cómo puedo usar el <%= Html.AntiForgeryToken() %>
en estos casos? ¿Debo incluir la llamada de ayuda dentro del parámetro de datos de la llamada Ajax?
Perdón por la larga publicación y muchas gracias por ayudar
EDITAR :
Según la respuesta de jayrdub , he usado de la siguiente manera
$("a.markAsDone").click(function (event) {
event.preventDefault();
$.ajax({
type: "post",
dataType: "html",
url: $(this).attr("rel"),
data: {
AddAntiForgeryToken({}),
id: parseInt($(this).attr("title"))
},
success: function (response) {
// ....
}
});
});
Respuestas:
Yo uso una simple función js como esta
Dado que cada formulario en una página tendrá el mismo valor para el token, simplemente coloque algo como esto en su página maestra superior
Luego, en su llamada ajax do (editado para que coincida con su segundo ejemplo)
fuente
AddAntiForgeryToken
, así:data: AddAntiForgeryToken({ id: parseInt($(this).attr("title")) }),
ajaxSend
o anularajax
para aumentar siempredata
con el token antifalsificación? Tal vez agregue algún control para asegurarse de queurl
esté destinado a su servidor.Me gusta la solución proporcionada por 360Airwalk, pero puede mejorarse un poco.
El primer problema es que si realiza
$.post()
con datos vacíos, jQuery no agrega unContent-Type
encabezado, y en este caso ASP.NET MVC no puede recibir y verificar el token. Por lo tanto, debe asegurarse de que el encabezado siempre esté allí.Otra mejora es el soporte de todos los verbos HTTP con contenido : POST, PUT, DELETE, etc. Aunque puede usar solo POSTs en su aplicación, es mejor tener una solución genérica y verificar que todos los datos que reciba con cualquier verbo tengan una falsificación simbólico.
fuente
.ajaxSend()
estados "A partir de jQuery 1.8, el método .ajaxSend () solo debe adjuntarse al documento". api.jquery.com/ajaxsendoptions
viene el que figura en laif
declaración final ? Gracias.Sé que hay muchas otras respuestas, pero este artículo es agradable y conciso y te obliga a revisar todos tus HttpPosts, no solo algunos de ellos:
http://richiban.wordpress.com/2013/02/06/validating-net-mvc-4-anti-forgery-tokens-in-ajax-requests/
Utiliza encabezados HTTP en lugar de intentar modificar la colección de formularios.
Servidor
Cliente
fuente
Me siento como un nigromante avanzado aquí, pero esto sigue siendo un problema 4 años después en MVC5.
Para manejar correctamente las solicitudes de ajax, el token antifalsificación debe pasarse al servidor en las llamadas de ajax. Integrarlo en sus datos y modelos de publicación es desordenado e innecesario. Agregar el token como un encabezado personalizado es limpio y reutilizable, y puede configurarlo para que no tenga que acordarse de hacerlo cada vez.
Hay una excepción: el discreto ajax no necesita un tratamiento especial para las llamadas de ajax. El token se pasa como de costumbre en el campo de entrada oculto normal. Exactamente lo mismo que un POST regular.
_Layout.cshtml
En _layout.cshtml tengo este bloque de JavaScript. No escribe el token en el DOM, sino que usa jQuery para extraerlo del literal de entrada oculto que genera el MVC Helper. La cadena mágica que es el nombre del encabezado se define como una constante en la clase de atributo.
Tenga en cuenta el uso de comillas simples en la función beforeSend: el elemento de entrada que se representa utiliza comillas dobles que romperían el literal de JavaScript.
JavaScript del cliente
Cuando esto se ejecuta, se llama a la función beforeSend anterior y AntiForgeryToken se agrega automáticamente a los encabezados de solicitud.
Biblioteca del servidor
Se requiere un atributo personalizado para procesar el token no estándar. Esto se basa en la solución de @ viggity, pero maneja el ajax discreto correctamente. Este código puede guardarse en su biblioteca común
Servidor / Controlador
Ahora solo aplica el atributo a su Acción. Aún mejor, puede aplicar el atributo a su controlador y todas las solicitudes serán validadas.
fuente
$.ajaxSetup
definir unbeforesend
controlador de eventos general , puede suceder que lo sobrescriba. Encontré otra solución donde puede agregar un segundo controlador que también se llamará. Funciona bien y no interrumpe su implementación.No usar Html.AntiForgeryToken . En su lugar, use AntiForgery.GetTokens y AntiForgery.Validate de la API web como se describe en Prevención de ataques de falsificación de solicitudes entre sitios (CSRF) en la aplicación ASP.NET MVC .
fuente
Estaba implementando este problema real en mi proyecto actual. Lo hice para todos los POST ajax que necesitaban un usuario autenticado.
En primer lugar, decidí conectar mis llamadas de jquery ajax para no repetirme con demasiada frecuencia. Este fragmento de JavaScript garantiza que todas las llamadas ajax (posteriores) agregarán mi token de validación de solicitud a la solicitud. Nota: el nombre .__RequestVerificationToken es utilizado por .Net framework para que pueda utilizar las características estándar de Anti-CSRF como se muestra a continuación.
En sus Vistas donde necesita que el token esté disponible para el javascript anterior, simplemente use el HTML-Helper común. Básicamente, puede agregar este código cuando lo desee. Lo puse dentro de una declaración if (Request.IsAuthenticated):
En su controlador simplemente use el mecanismo estándar ASP.Net MVC Anti-CSRF. Lo hice así (aunque en realidad usé Salt).
Con Firebug o una herramienta similar, puede ver fácilmente cómo sus solicitudes POST ahora tienen un parámetro __RequestVerificationToken adjunto.
fuente
Creo que todo lo que tiene que hacer es asegurarse de que la entrada "__RequestVerificationToken" esté incluida en la solicitud POST. La otra mitad de la información (es decir, el token en la cookie del usuario) ya se envía automáticamente con una solicitud POST de AJAX.
P.ej,
fuente
AntiForgeryToken
, de todos modos es discutible. Si lo hace (no estoy seguro de cómo obtendrá uno en ese caso, pero suponiendo que lo sea), entonces lo anterior funcionaría bien. Si está intentando crear una página web sencilla que publicará una solicitud en un servidor que espera dicho token, y el servidor no generó dicha página, entonces no tiene suerte. Ese es esencialmente el punto de AntiForgeryToken ...También puedes hacer esto:
Esto está usando
Razor
, pero si está usando laWebForms
sintaxis, también puede usar<%= %>
etiquetasfuente
Además de mi comentario en contra de la respuesta de @ JBall que me ayudó en el camino, esta es la respuesta final que funciona para mí. Estoy usando MVC y Razor y estoy enviando un formulario usando jQuery AJAX para poder actualizar una vista parcial con algunos resultados nuevos y no quería hacer una devolución completa (y un parpadeo de página).
Añade el
@Html.AntiForgeryToken()
interior del formulario como de costumbre.Mi código de botón de envío AJAX (es decir, un evento onclick) es:
He dejado la acción "éxito", ya que muestra cómo se está actualizando la vista parcial que contiene un MvcJqGrid y cómo se está actualizando (una cuadrícula jqGrid muy poderosa y este es un brillante envoltorio MVC).
Mi método de controlador se ve así:
Tengo que admitir que no soy fanático de PUBLICAR los datos de un formulario completo como un Modelo, pero si necesita hacerlo, esta es una forma de funcionar. MVC simplemente hace que el enlace de datos sea demasiado fácil, así que en lugar de someter 16 valores individuales (o una FormCollection de tipo débil), está bien, supongo. Si sabe mejor, avíseme, ya que quiero producir un código MVC C # robusto.
fuente
Encontré esta idea muy inteligente en https://gist.github.com/scottrippey/3428114 por cada llamada $ .ajax modifica la solicitud y agrega el token.
fuente
if (options.contentType != false && options.contentType.indexOf('application/json') === 0) {
para capturar llamadas Ajax que no habían especificado un tipo de contenido1.Defina la función para obtener el token del servidor
2. Obtenga el token y configure el encabezado antes de enviarlo al servidor
3. Validación del servidor en HttpRequestBase en el método que maneja Publicar / obtener
fuente
Sé que ha pasado algún tiempo desde que se publicó esta pregunta, pero encontré un recurso realmente útil, que analiza el uso de AntiForgeryToken y hace que sea menos problemático de usar. También proporciona el complemento jquery para incluir fácilmente el token antiforgery en llamadas AJAX:
Recetas de solicitud antifalsificación para ASP.NET MVC y AJAX
No estoy contribuyendo mucho, pero tal vez alguien lo encuentre útil.
fuente
fuente
Aquí está la forma más fácil que he visto. Nota: Asegúrese de tener "@ Html.AntiForgeryToken ()" en su Vista
fuente
Ligera mejora a la solución 360Airwalk. Esto incrusta el token Anti falsificación dentro de la función de JavaScript, por lo que @ Html.AntiForgeryToken () ya no necesita ser incluido en cada vista.
fuente
fuente
Estoy usando una publicación ajax para ejecutar un método de eliminación (resulta ser de una línea de tiempo de visjs pero eso no es relevante). Esto es lo que digo:
Este es mi Index.cshtml
Todo lo que agregué aquí fue
@Html.AntiForgeryToken()
hacer que el token apareciera en la páginaLuego, en mi publicación de ajax, utilicé:
Que agrega el valor del token, raspado de la página, a los campos publicados
Antes de esto intenté poner el valor en los encabezados pero obtuve el mismo error
Siéntase libre de publicar mejoras. Esto ciertamente parece ser un enfoque simple que puedo entender.
fuente
De acuerdo, muchas publicaciones aquí, ninguna de ellas me ayudó, días y días de google, y aún no llegué al punto de escribir toda la aplicación desde cero, y luego noté esta pequeña pepita en mi Web.confg
Ahora no sé por qué lo agregué, sin embargo, ya lo noté, se ignora en modo de depuración y no en modo de producción (IE instalado en IIS en algún lugar)
Para mí, la solución era una de 2 opciones, ya que no recuerdo por qué lo agregué, no puedo estar seguro de que otras cosas no dependan de él, y en segundo lugar, el nombre de dominio debe estar en minúsculas y un TLD no como lo he hecho. en * .localLookup.net
Tal vez ayuda, tal vez no. Espero que ayude a alguien
fuente
La solución que encontré no es para ASPX sino para Razor, sino un problema bastante competitivo.
Lo resolví agregando el AntiForgery a la solicitud. HTML Helper no crea una identificación HTML con la llamada
Para agregar el token a la solicitud posterior, acabo de agregar la identificación de AntiForgery al campo oculto con jquery:
Esto provocó que el controlador aceptara la solicitud con el atributo [ValidateAntiForgeryToken]
fuente
AntiforgeryToken sigue siendo un dolor, ninguno de los ejemplos anteriores funcionó palabra por palabra para mí. Demasiados para allí. Así que los combiné todos. Necesita un @ Html.AntiforgeryToken en una forma dando vueltas por iirc
Resuelto así:
En caso de duda, agregue más signos $
fuente