Je pourrais utiliser un peu d'aide pour me conformer au mécanisme de protection CSRF de Django via mon article AJAX. J'ai suivi les instructions ici:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
J'ai copié exactement l'exemple de code AJAX qu'ils ont sur cette page:
http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
J'ai mis une alerte imprimant le contenu de getCookie('csrftoken')
avant l' xhr.setRequestHeader
appel et elle est en effet peuplée de quelques données. Je ne sais pas comment vérifier que le jeton est correct, mais je suis encouragé qu'il trouve et envoie quelque chose.
Mais Django rejette toujours mon message AJAX.
Voici mon JavaScript:
$.post("/memorize/", data, function (result) {
if (result != "failure") {
get_random_card();
}
else {
alert("Failed to save card data.");
}
});
Voici l'erreur que je vois de Django:
[23 / février / 2011 22:08:29] "POST / memorize / HTTP / 1.1" 403 2332
Je suis sûr qu'il me manque quelque chose, et c'est peut-être simple, mais je ne sais pas ce que c'est. J'ai cherché autour de SO et j'ai vu des informations sur la désactivation du contrôle CSRF pour ma vue via le csrf_exempt
décorateur, mais je trouve cela peu attrayant. J'ai essayé cela et cela fonctionne, mais je préfère que mon POST fonctionne comme Django a été conçu pour s'y attendre, si possible.
Juste au cas où cela serait utile, voici l'essentiel de ce que fait mon point de vue:
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))
Merci pour vos réponses!
Réponses:
Une vraie solution
Ok, j'ai réussi à retracer le problème. Il réside dans le code Javascript (comme je l'ai suggéré ci-dessous).
Voici ce dont vous avez besoin:
au lieu du code publié dans la documentation officielle: https://docs.djangoproject.com/en/2.2/ref/csrf/
Le code de travail, provient de cette entrée Django: http://www.djangoproject.com/weblog/2011/feb/08/security/
La solution générale est donc: "utiliser le gestionnaire ajaxSetup au lieu du gestionnaire ajaxSend". Je ne sais pas pourquoi ça marche. Mais cela fonctionne pour moi :)
Article précédent (sans réponse)
Je rencontre le même problème en fait.
Cela se produit après la mise à jour vers Django 1.2.5 - il n'y avait pas d'erreurs avec les requêtes AJAX POST dans Django 1.2.4 (AJAX n'était en aucun cas protégé, mais cela fonctionnait très bien).
Tout comme OP, j'ai essayé l'extrait de code JavaScript publié dans la documentation Django. J'utilise jQuery 1.5. J'utilise également le middleware "django.middleware.csrf.CsrfViewMiddleware".
J'ai essayé de suivre le code du middleware et je sais que cela échoue:
puis
ce "si" est vrai, car "request_csrf_token" est vide.
Fondamentalement, cela signifie que l'en-tête n'est PAS défini. Alors, y a-t-il quelque chose qui ne va pas avec cette ligne JS:
?
J'espère que les détails fournis nous aideront à résoudre le problème :)
la source
ajaxSetup
plutôt queajaxSend
va à l'encontre de la documentation jQuery: api.jquery.com/jQuery.ajaxSetupSi vous utilisez la
$.ajax
fonction, vous pouvez simplement ajouter lecsrf
jeton dans le corps de données:la source
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
csrfmiddlewaretoken: '{{ csrf_token }}'
à mondata
dictionnaire lors d'un$.post
appel.Ajoutez cette ligne à votre code jQuery:
Et.. Voila.
la source
CSRF Failed: CSRF token missing or incorrect.
Le problème est que django s'attend à ce que la valeur du cookie soit renvoyée dans le cadre des données du formulaire. Le code de la réponse précédente demande à javascript de rechercher la valeur du cookie et de la placer dans les données du formulaire. C'est une belle façon de le faire d'un point de vue technique, mais cela semble un peu verbeux.
Dans le passé, je l'ai fait plus simplement en demandant au javascript de mettre la valeur du jeton dans les données de publication.
Si vous utilisez {% csrf_token%} dans votre modèle, vous obtiendrez un champ de formulaire masqué émis qui porte la valeur. Mais, si vous utilisez {{csrf_token}}, vous obtiendrez simplement la valeur nue du jeton, vous pouvez donc l'utiliser en javascript comme ceci ...
Ensuite, vous pouvez inclure cela, avec le nom de clé requis dans le hachage que vous soumettez ensuite en tant que données à l'appel ajax.
la source
window
objet, afin qu'elles soient accessibles par la suite. Même dans les fichiers statiques.Les
{% csrf_token %}
modèles html mis à l'intérieur<form></form>
se traduit par quelque chose comme:
alors pourquoi ne pas simplement le grep dans votre JS comme ceci:
puis passez-le, par exemple en effectuant un POST, comme:
la source
Réponse non-jquery:
usage:
la source
Si votre formulaire se poste correctement dans Django sans JS, vous devriez pouvoir l'améliorer progressivement avec ajax sans aucun piratage ou passage désordonné du jeton csrf. Sérialisez simplement le formulaire entier et cela récupérera automatiquement tous vos champs de formulaire, y compris le champ csrf caché:
J'ai testé cela avec Django 1.3+ et jQuery 1.5+. Évidemment, cela fonctionnera pour n'importe quel formulaire HTML, pas seulement pour les applications Django.
la source
Utilisez Firefox avec Firebug. Ouvrez l'onglet «Console» lors du lancement de la requête ajax. Avec
DEBUG=True
vous obtenez la belle page d'erreur django comme réponse et vous pouvez même voir le HTML rendu de la réponse ajax dans l'onglet console.Ensuite, vous saurez quelle est l'erreur.
la source
La réponse acceptée est probablement un hareng rouge. La différence entre Django 1.2.4 et 1.2.5 était l'exigence d'un jeton CSRF pour les requêtes AJAX.
Je suis tombé sur ce problème sur Django 1.3 et il était dû au fait que le cookie CSRF n'était pas défini en premier lieu. Django ne définira pas le cookie à moins qu'il ne le soit. Ainsi, un site exclusivement ou fortement ajax fonctionnant sous Django 1.2.4 n'aurait potentiellement jamais envoyé de jeton au client et la mise à niveau nécessitant le jeton provoquerait les erreurs 403.
La solution idéale est ici: http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form
mais vous devrez attendre 1.4 à moins ce n'est que de la documentation rattrapant le code
Éditer
Notez également que la dernière documentation Django note un bogue dans jQuery 1.5, alors assurez-vous que vous utilisez la version 1.5.1 ou ultérieure avec le code suggéré par Django: http://docs.djangoproject.com/en/1.3/ref/contrib/csrf/# Ajax
la source
ensure_csrf_cookie
qui vous permet d'envelopper une vue pour vous assurer qu'il envoie le cookie.csrftoken
cookie en premier lieu, merci!Il semble que personne n'ait mentionné comment faire cela en pur JS en utilisant l'en-
X-CSRFToken
tête et{{ csrf_token }}
, voici donc une solution simple où vous n'avez pas besoin de rechercher dans les cookies ou le DOM:la source
Comme cela n'est indiqué nulle part dans les réponses actuelles, la solution la plus rapide si vous n'intégrez pas js dans votre modèle est:
Mettez
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
avant votre référence au fichier script.js dans votre modèle, puis ajoutezcsrfmiddlewaretoken
dans votredata
dictionnaire dans votre fichier js:la source
Je viens de rencontrer une situation un peu différente mais similaire. Je ne sais pas à 100% si ce serait une solution à votre cas, mais j'ai résolu le problème pour Django 1.3 en définissant un paramètre POST 'csrfmiddlewaretoken' avec la chaîne de valeur de cookie appropriée qui est généralement renvoyée sous la forme de votre HTML personnel par Django système de modèle avec la balise '{% csrf_token%}'. Je n'ai pas essayé l'ancien Django, juste arrivé et résolu sur Django1.3. Mon problème était que la première demande soumise via Ajax à partir d'un formulaire a été effectuée avec succès, mais la deuxième tentative de la même chose a échoué, a abouti à l'état 403 même si l'en-tête 'X-CSRFToken' est correctement placé avec la valeur du jeton CSRF également comme dans le cas de la première tentative. J'espère que cela t'aides.
Cordialement,
Hiro
la source
vous pouvez coller ce js dans votre fichier html, n'oubliez pas de le mettre avant une autre fonction js
la source
Un jeton CSRF est attribué à chaque session (c'est-à-dire à chaque fois que vous vous connectez). Donc, avant de souhaiter obtenir des données saisies par l'utilisateur et de les envoyer en tant qu'appel ajax à une fonction protégée par le décorateur csrf_protect, essayez de trouver les fonctions qui sont appelées avant d'obtenir ces données de l'utilisateur. Par exemple, un modèle doit être rendu sur lequel votre utilisateur entre des données. Ce modèle est rendu par une fonction. Dans cette fonction, vous pouvez obtenir le jeton csrf comme suit: csrf = request.COOKIES ['csrftoken'] Passez maintenant cette valeur csrf dans le dictionnaire contextuel par rapport au modèle en question. Maintenant, dans ce modèle, écrivez cette ligne: Maintenant, dans votre fonction javascript, avant de faire une requête ajax, écrivez ceci: var csrf = $ ('# csrf'). val () cela choisira la valeur du jeton passé au modèle et la stockera dans la variable csrf. Maintenant, lors de l'appel ajax, dans vos données de publication, transmettez également cette valeur: "csrfmiddlewaretoken": csrf
Cela fonctionnera même si vous n'implémentez pas de formulaires django.
En fait, la logique ici est la suivante: vous avez besoin d'un jeton que vous pouvez obtenir à partir de la demande. Il vous suffit donc de déterminer la fonction appelée immédiatement après la connexion. Une fois que vous avez ce jeton, effectuez un autre appel ajax pour l'obtenir ou passez-le à un modèle accessible par votre ajax.
la source
csrftoken: csrftoken
plutôt quecsrfmiddlwaretoken: csrftoken
. Après le changement, cela a fonctionné. Mercipour quelqu'un qui rencontre ceci et essaie de déboguer:
1) le test django csrf (en supposant que vous en envoyez un) est ici
2) Dans mon cas,
settings.CSRF_HEADER_NAME
était défini sur «HTTP_X_CSRFTOKEN» et mon appel AJAX envoyait un en-tête nommé «HTTP_X_CSRF_TOKEN», donc les choses ne fonctionnaient pas. Je pourrais le changer dans l'appel AJAX ou dans le paramètre django.3) Si vous choisissez de le changer côté serveur, trouvez votre emplacement d'installation de django et lancez un point d'arrêt dans le
csrf middleware
.f que vous utilisezvirtualenv
, ce sera quelque chose comme:~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py
Ensuite, assurez-vous que le
csrf
jeton provient correctement de la demande.4) Si vous avez besoin de changer votre en-tête, etc. - modifiez cette variable dans votre fichier de paramètres
la source
Si quelqu'un se débat avec axios pour faire ce travail, cela m'a aidé:
Source: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/
la source
Dans mon cas, le problème était avec la configuration nginx que j'ai copiée du serveur principal vers un serveur temporaire avec la désactivation de https qui n'est pas nécessaire sur le second dans le processus.
J'ai dû commenter ces deux lignes dans la configuration pour que cela fonctionne à nouveau:
la source
Voici une solution moins verbeuse fournie par Django:
Source: https://docs.djangoproject.com/en/1.11/ref/csrf/
la source