Podría usar un poco de ayuda para cumplir con el mecanismo de protección CSRF de Django a través de mi publicación AJAX. He seguido las instrucciones aquí:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
Copié exactamente el código de muestra AJAX que tienen en esa página exactamente:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Puse una alerta imprimiendo el contenido de getCookie('csrftoken')
antes de la xhr.setRequestHeader
llamada y de hecho está poblada con algunos datos. No estoy seguro de cómo verificar que el token sea correcto, pero me alienta que encuentre y envíe algo.
Pero Django sigue rechazando mi publicación AJAX.
Aquí está mi JavaScript:
$.post("/memorize/", data, function (result) {
if (result != "failure") {
get_random_card();
}
else {
alert("Failed to save card data.");
}
});
Aquí está el error que estoy viendo de Django:
[23 / Feb / 2011 22:08:29] "POST / memorizar / HTTP / 1.1" 403 2332
Estoy seguro de que me falta algo, y tal vez sea simple, pero no sé qué es. He buscado alrededor de SO y vi información sobre cómo desactivar la verificación CSRF para mi vista a través del csrf_exempt
decorador, pero me parece poco atractivo. Lo probé y funciona, pero prefiero que mi POST funcione de la manera en que Django fue diseñado para esperarlo, si es posible.
En caso de que sea útil, aquí está la esencia de lo que está haciendo mi punto de vista:
def myview(request):
profile = request.user.profile
if request.method == 'POST':
"""
Process the post...
"""
return HttpResponseRedirect('/memorize/')
else: # request.method == 'GET'
ajax = request.GET.has_key('ajax')
"""
Some irrelevent code...
"""
if ajax:
response = HttpResponse()
profile.get_stack_json(response)
return response
else:
"""
Get data to send along with the content of the page.
"""
return render_to_response('memorize/memorize.html',
""" My data """
context_instance=RequestContext(request))
Gracias por tus respuestas!
Respuestas:
Solución real
Ok, logré rastrear el problema. Se encuentra en el código Javascript (como sugerí a continuación).
Lo que necesitas es esto:
en lugar del código publicado en los documentos oficiales: https://docs.djangoproject.com/en/2.2/ref/csrf/
El código de trabajo proviene de esta entrada de Django: http://www.djangoproject.com/weblog/2011/feb/08/security/
Entonces, la solución general es: "usar el controlador ajaxSetup en lugar del controlador ajaxSend". No sé por qué funciona. Pero funciona para mí :)
Publicación anterior (sin respuesta)
Estoy experimentando el mismo problema en realidad.
Ocurre después de actualizar a Django 1.2.5: no hubo errores con las solicitudes POST de AJAX en Django 1.2.4 (AJAX no estaba protegido de ninguna manera, pero funcionó bien).
Al igual que OP, probé el fragmento de JavaScript publicado en la documentación de Django. Estoy usando jQuery 1.5. También estoy usando el middleware "django.middleware.csrf.CsrfViewMiddleware".
Traté de seguir el código de middleware y sé que falla en esto:
y entonces
este "si" es verdadero, porque "request_csrf_token" está vacío.
Básicamente significa que el encabezado NO está configurado. Entonces, ¿hay algo malo con esta línea JS:
?
Espero que los detalles proporcionados nos ayuden a resolver el problema :)
fuente
ajaxSetup
lugar deajaxSend
ejecutar en contra de los documentos de jQuery: api.jquery.com/jQuery.ajaxSetupSi usa la
$.ajax
función, simplemente puede agregar elcsrf
token en el cuerpo de datos:fuente
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
csrfmiddlewaretoken: '{{ csrf_token }}'
a midata
diccionario en una$.post
llamada.Agregue esta línea a su código jQuery:
y hecho.
fuente
CSRF Failed: CSRF token missing or incorrect.
El problema se debe a que django espera que el valor de la cookie se transfiera como parte de los datos del formulario. El código de la respuesta anterior está haciendo que JavaScript busque el valor de la cookie y lo coloque en los datos del formulario. Es una forma encantadora de hacerlo desde un punto de vista técnico, pero se ve un poco detallado.
En el pasado, lo hice más simplemente obteniendo el javascript para poner el valor del token en los datos de la publicación.
Si utiliza {% csrf_token%} en su plantilla, obtendrá un campo de formulario oculto que lleva el valor. Pero, si usa {{csrf_token}}, obtendrá el valor básico del token, por lo que puede usarlo en JavaScript de esta manera ...
Luego puede incluir eso, con el nombre de clave requerido en el hash que luego envía como datos a la llamada ajax.
fuente
window
objeto, para que luego sean accesibles. Incluso en archivos estáticos.El
{% csrf_token %}
poner en plantillas html dentro<form></form>
se traduce en algo como:
Entonces, ¿por qué no simplemente ponerlo en tu JS así:
y luego pasarlo, por ejemplo, haciendo POST, como:
fuente
Respuesta no jquery:
uso:
fuente
Si tu formulario se publica correctamente en Django sin JS, deberías poder mejorarlo progresivamente con ajax sin ningún tipo de pirateo o transferencia desordenada del token csrf. Simplemente serialice todo el formulario y eso recogerá automáticamente todos sus campos de formulario, incluido el campo oculto csrf:
He probado esto con Django 1.3+ y jQuery 1.5+. Obviamente, esto funcionará para cualquier formulario HTML, no solo para las aplicaciones de Django.
fuente
Usa Firefox con Firebug. Abra la pestaña 'Consola' mientras dispara la solicitud ajax. Con
DEBUG=True
usted obtiene la bonita página de error de django como respuesta e incluso puede ver el html representado de la respuesta ajax en la pestaña de la consola.Entonces sabrás cuál es el error.
fuente
La respuesta aceptada es muy probablemente un arenque rojo. La diferencia entre Django 1.2.4 y 1.2.5 era el requisito de un token CSRF para solicitudes AJAX.
Encontré este problema en Django 1.3 y fue causado por la cookie CSRF no configurada en primer lugar. Django no configurará la cookie a menos que sea necesario. Por lo tanto, un sitio exclusivo o muy ajax que se ejecute en Django 1.2.4 nunca podría haber enviado un token al cliente y luego la actualización que requiere el token podría causar los errores 403.
La solución ideal está aquí: http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form
pero tendrías que esperar 1.4 a menos esto es solo documentación que se pone al día con el código
Editar
Tenga en cuenta también que los documentos posteriores de Django notan un error en jQuery 1.5, así que asegúrese de estar utilizando 1.5.1 o posterior con el código sugerido de Django: http://docs.djangoproject.com/en/1.3/ref/contrib/csrf/# ajax
fuente
ensure_csrf_cookie
que puede ajustar alrededor de una vista para asegurarse de que envía la cookie.csrftoken
cookies en primer lugar, ¡gracias!Parece que nadie ha mencionado cómo hacer esto en JS puro usando el
X-CSRFToken
encabezado y{{ csrf_token }}
, así que aquí hay una solución simple donde no necesita buscar a través de las cookies o el DOM:fuente
Como no se indica en ninguna parte de las respuestas actuales, la solución más rápida si no está incrustando js en su plantilla es:
Ponga
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
antes de su referencia al archivo script.js en su plantilla, luego agreguecsrfmiddlewaretoken
a sudata
diccionario en su archivo js:fuente
Acabo de encontrar una situación un poco diferente pero similar. No estoy 100% seguro de si sería una resolución para su caso, pero resolví el problema para Django 1.3 configurando un parámetro POST 'csrfmiddlewaretoken' con la cadena de valor de cookie adecuada que Django devuelve generalmente en la forma de su HTML de inicio. sistema de plantillas con la etiqueta '{% csrf_token%}'. No probé el Django anterior, simplemente sucedió y resolví en Django1.3. Mi problema fue que la primera solicitud enviada a través de Ajax desde un formulario se realizó con éxito, pero el segundo intento exacto del mismo falló, resultó en un estado 403 a pesar de que el encabezado 'X-CSRFToken' también se coloca correctamente con el valor de token CSRF también como en el caso del primer intento. Espero que esto ayude.
Saludos,
Hiro
fuente
puede pegar este js en su archivo html, recuerde ponerlo antes de otra función js
fuente
Se asigna un token CSRF a cada sesión (es decir, cada vez que inicia sesión). Entonces, antes de que desee obtener algunos datos ingresados por el usuario y enviarlos como una llamada ajax a alguna función que esté protegida por el decorador csrf_protect, intente encontrar las funciones que se están llamando antes de obtener estos datos del usuario. Por ejemplo, se debe representar una plantilla en la que su usuario está ingresando datos. Esa plantilla está siendo representada por alguna función. En esta función, puede obtener el token csrf de la siguiente manera: csrf = request.COOKIES ['csrftoken'] Ahora pase este valor csrf en el diccionario de contexto contra el cual se representa la plantilla en cuestión. Ahora en esa plantilla escriba esta línea: Ahora en su función javascript, antes de hacer una solicitud ajax, escriba esto: var csrf = $ ('# csrf'). val () esto elegirá el valor del token pasado a la plantilla y lo almacenará en la variable csrf. Ahora, mientras realiza una llamada ajax, en sus datos de publicación, pase este valor también: "csrfmiddlewaretoken": csrf
Esto funcionará incluso si no está implementando formularios django.
De hecho, la lógica aquí es: necesita un token que puede obtener de la solicitud. Por lo tanto, solo necesita averiguar la función que se llama inmediatamente después de iniciar sesión. Una vez que tenga este token, realice otra llamada ajax para obtenerlo o páselo a alguna plantilla a la que pueda acceder su ajax.
fuente
csrftoken: csrftoken
lugar decsrfmiddlwaretoken: csrftoken
. Después del cambio, funcionó. Graciaspara alguien que se encuentra con esto y está tratando de depurar:
1) el cheque csrf de django (suponiendo que está enviando uno) está aquí
2) En mi caso,
settings.CSRF_HEADER_NAME
estaba configurado en 'HTTP_X_CSRFTOKEN' y mi llamada AJAX estaba enviando un encabezado llamado 'HTTP_X_CSRF_TOKEN', por lo que las cosas no funcionaban. Podría cambiarlo en la llamada AJAX o en la configuración de django.3) Si opta por cambiarlo en el lado del servidor, busque su ubicación de instalación de django y arroje un punto de interrupción en el
csrf middleware
.f que está utilizandovirtualenv
, será algo así como:~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py
Luego, asegúrese de que el
csrf
token se obtenga correctamente de la solicitud.4) Si necesita cambiar su encabezado, etc., cambie esa variable en su archivo de configuración
fuente
Si alguien está luchando con los axios para que esto funcione, esto me ayudó:
Fuente: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/
fuente
En mi caso, el problema fue con la configuración de nginx que he copiado del servidor principal a uno temporal con la desactivación de https que no es necesaria en el segundo en el proceso.
Tuve que comentar estas dos líneas en la configuración para que funcione nuevamente:
fuente
Aquí hay una solución menos detallada proporcionada por Django:
Fuente: https://docs.djangoproject.com/en/1.11/ref/csrf/
fuente