Appel AJAX csurf – jeton CSRF non valide

J’utilise le logiciel intermédiaire csurf pour la protection CSRF. Si je l’utilise avec des formulaires, où je mets le jeton dans un champ caché, l’action derrière les itinéraires fonctionne. Maintenant, je veux faire un simple appel AJAX mais csurf dit que ce n’est pas valide.

Appel AJAX:

$('.remove').on('click', function () { var csrf = $(this).attr('data-csrf'); $.ajax({ type: 'DELETE', url: '/user/' + $(this).attr('data-id'), data: { _csrf: csrf }, success: function (data) { //..... } }); }); 

Et la partie dans la vue:

    

Et l’init du middleware:

 import * as csurf from 'csurf'; // init bodyparse and and and... app.use(csurf()); 

Je ne connais pas Express, mais le jeton CSRF est généralement contenu dans un cookie. Vous aurez donc besoin de ces deux fonctions:

  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; } function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } 

Et alors:

 var csrftoken = getCookie('csrftoken'); $.ajax({    url : formURL,    type: "POST",    data : postData, beforeSend: function(xhr, settings){ if (!csrfSafeMethod(settings.type)) xhr.setRequestHeader("X-CSRFToken", csrftoken); },    success:function(data, textStatus, jqXHR){    },    error: function(jqXHR, textStatus, errorThrown){        //if fails    } }); 

Ou si vous ne souhaitez pas utiliser jQuery, vous pouvez utiliser XMLHttpRequest pour effectuer la demande AJAX:

 var csrftoken = getCookie('csrftoken'); var xhr = new XMLHttpRequest(); xhr.open('POST', url); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.setRequestHeader("X-CSRFToken", csrftoken); xhr.onload = function(){ if(xhr.status === 200){ var response = JSON.parse(xhr.responseText); console.log(response) } }; xhr.send(encodeURI('category=' + cat)); 

La seule raison pour laquelle cette méthode ne fonctionne pas, c’est que vous ne transmettez pas de cookies avec votre demande ajax. Je me débattais quand je le découvrais quand je cherchais dans le code.

Csurf a besoin de vous pour passer la clé secrète qui est stockée sur les cookies ( _csrf ). Les cookies ont une limitation par la permission basée sur le domaine (sauf votre serveur autorisant CORS)

Sur mon cas, j’utilise fetch pour transmettre les cookies avec la même demande de domaine (je n’ai pas à autoriser CORS)

 const { _csrf, someData } = jsonData; // _csrf here you got from the form const response = await fetch("/api/some/endpoint", { method: "POST", credentials: "same-origin", // here is the option to include cookies on this request headers: { "x-csrf-token": _csrf, "Content-Type": "application/json" }, body: JSON.ssortingngify({ someData }) }); 

Veuillez noter le code ci-dessus, j’utilise le format es6. Vous pouvez changer la same-origin avec include si vous faites une demande dans un autre domaine, appelé CORS, voir le doc ici

Si vous utilisez jQuery comme bibliothèque, ce code pourrait vous être utile. Ce code n’a pas été testé et vous devriez le découvrir vous-même en fonction de la bibliothèque que vous utilisez.

  $.ajax({ url: 'http://your.domain.com/api/some/endpoint', xhrFields: { withCredentials: true }, // this include cookies headers: {'x-csrf-token': 'YourCSRFKey'} }) 

Soyez libre d’utiliser vos propres noms dans les en- têtes , les données de publication ou la chaîne de requête lors de la transmission de la valeur _csrf . Dans mon exemple ci-dessus, j’utilise un en-tête avec le nom x-csrf-token , mais vous pouvez utiliser une autre méthode basée sur le code de capture d’écran ci-dessous.

Exemple de code provenant de csurf lors de l'obtention de la valeur _csrf