«Jeton CSRF manquant ou incorrect» lors de la publication du paramètre via AJAX dans Django

J’essaie de poster paramètre comme

jQuery.ajax( { 'type': 'POST', 'url': url, 'contentType': 'application/json', 'data': "{content:'xxx'}", 'dataType': 'json', 'success': rateReviewResult } ); 

Cependant, Django retourne Forbidden 403. CSRF verification failed. Request aborted. Forbidden 403. CSRF verification failed. Request aborted. J’utilise 'django.middleware.csrf.CsrfViewMiddleware' et je n’ai pas trouvé comment prévenir ce problème sans compromettre la sécurité.

Vous pouvez créer une demande de publication AJAX de deux manières différentes:

  1. Dire à votre vue de ne pas vérifier le jeton csrf. Cela peut être fait en utilisant le décorateur @csrf_exempt , comme ceci:

     from django.views.decorators.csrf import csrf_exempt @csrf_exempt def your_view_name(request): ... 
  2. Pour incorporer un jeton csrf dans chaque requête AJAX, jQuery peut être:

     $(function () { $.ajaxSetup({ headers: { "X-CSRFToken": getCookie("csrftoken") } }); }); 

    Où la fonction getCookie récupère le jeton csrf des cookies. J’utilise l’implémentation suivante:

     function getCookie(c_name) { if (document.cookie.length > 0) { c_start = document.cookie.indexOf(c_name + "="); if (c_start != -1) { c_start = c_start + c_name.length + 1; c_end = document.cookie.indexOf(";", c_start); if (c_end == -1) c_end = document.cookie.length; return unescape(document.cookie.subssortingng(c_start,c_end)); } } return ""; } 

    De plus, jQuery a un plugin pour accéder aux cookies, quelque chose comme ça:

     // set cookie $.cookie('cookiename', 'cookievalue');
    // read cookie var myCookie = $.cookie('cookiename');
    // delete cookie $.cookie('cookiename', null);

Le moyen le plus simple que j’ai trouvé est d’inclure la valeur {{csrf_token}} dans les données:

 jQuery.ajax( { 'type': 'POST', 'url': url, 'contentType': 'application/json', 'data': { 'content': 'xxx', 'csrfmiddlewaretoken': '{{ csrf_token }}', }, 'dataType': 'json', 'success': rateReviewResult } ); 

Il m’a fallu du temps pour comprendre quoi faire avec le code que Daniel a posté. Mais en fait, tout ce que vous avez à faire est de le coller au début du fichier javascript.

Pour moi, la meilleure solution à ce jour est la suivante:

  1. Créez un fichier csrf.js

  2. Collez le code dans le fichier csrf.js

  3. Référencez le code dans le modèle dont vous avez besoin

      

Notez que STATIC_PREFIX/js/csrf.js pointe vers mon fichier. Je charge actuellement la variable STATIC_PREFIX avec {% get_static_prefix as STATIC_PREFIX %} .


base.html avancée: si vous utilisez des templates et que vous utilisez quelque chose comme base.html , vous pouvez simplement référencer le script à partir de là et vous n’avez plus à vous soucier des autres fichiers. Pour autant que je sache, cela ne devrait pas non plus poser de problème de sécurité.

Simple et court

 $.ajaxSetup({ headers: { "X-CSRFToken": '{{csrf_token}}' } }); 

OU

 function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", '{{csrf_token}}'); } } }); 

docs

J’ai eu le même problème hier et j’ai pensé que cela aiderait les gens s’il y avait un moyen simple de le gérer, alors j’ai écrit un plugin jQuery pour cela: jquery.djangocsrf . Au lieu d’append le jeton CSRF à chaque requête, il se connecte à l’événement AjaxSend jQuery et ajoute le cookie client dans un en-tête.

Voici comment l’utiliser:

1- l’incluez:

    

2- activez le dans votre code:

 $.djangocsrf( "enable" ); 

Django ajoute toujours le jeton dans un cookie si votre modèle utilise {% csrf_token %} . Pour vous assurer qu’il l’ajoute toujours même si vous n’utilisez pas la balise spéciale dans votre modèle, utilisez le décorateur @ensure_csrf_cookie :

 from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def my_view(request): return render(request, 'mytemplate.html') 

Note: J’utilise Django 1.6.2.

Merci à tous pour toutes les réponses. J’utilise Django 1.5.1. Je suis un peu en retard à la fête, mais voilà.

J’ai trouvé le lien vers le projet Django très utile, mais je ne voulais pas vraiment inclure le code JavaScript supplémentaire chaque fois que je voulais faire un appel Ajax.

J’aime la réponse de jerrykan car elle est très succincte et ajoute seulement une ligne à un appel Ajax par ailleurs normal. En réponse aux commentaires sous son commentaire concernant les situations où les balises de modèle Django ne sont pas disponibles, pourquoi ne pas charger le fichier csrfmiddlewaretoken à partir du DOM?

 var token = $('input[name="csrfmiddlewaretoken"]').prop('value'); jQuery.ajax({ type: 'POST', url: url, data: { 'csrfmiddlewaretoken': token }, dataType: 'json', success: function(data) { console.log('Yippee! ' + data); } }); 

EDIT Mars 2016

Mon approche de cette question au cours des dernières années a changé. J’ajoute le code ci-dessous (à partir des documents Django ) dans un fichier main.js et le charge sur chaque page. Une fois cela fait, vous ne devriez plus avoir à vous soucier du jeton CSRF avec ajax.

 function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); 

Inclure l’en x-csrftoken tête x-csrftoken dans la requête:

 var token = $('input[name="csrfmiddlewaretoken"]').prop('value'); jQuery.ajax({ type: 'POST', url: url, beforeSend : function(jqXHR, settings) { jqXHR.setRequestHeader("x-csrftoken", get_the_csrf_token_from_cookie()); }, data: data, dataType: 'json', }); 

En l’absence d’une réponse directe, il vous suffit d’append l’en-tête X-CSRFToken à la requête ajax qui se trouve dans le cookie csrftoken . JQuery ne fait pas les cookies (pour une raison quelconque) sans plugin donc:

  

et le changement de code minimal est:

 $.ajax({ headers: { "X-CSRFToken": $.cookie("csrftoken") }, ... }); 

Si, après avoir lu d’autres réponses, quelqu’un a encore du mal, essayez ceci:

  $.ajax({ type: "POST", beforeSend: function (request) { request.setRequestHeader("X-CSRF-TOKEN", "${_csrf.token}"); }, url: servlet_path, data : data, success : function(result) { console.log("Success!"); } }); 

La solution la plus rapide sans plug-ins si vous n’incluez pas js dans votre modèle est la suivante:

Mettez avant votre référence au fichier script.js dans votre modèle, puis ajoutez csrfmiddlewaretoken dans votre dictionnaire de data :

 $.ajax({ type: 'POST', url: somepathname + "do_it/", data: {csrfmiddlewaretoken: window.CSRF_TOKEN}, success: function() { console.log("Success!"); } }) 

Si vous incorporez vos js dans le modèle, c’est aussi simple que: data: {csrfmiddlewaretoken: '{{ csrf_token }}'}