web-dev-qa-db-fra.com

Comment inclure le jeton CSRF dans les en-têtes de la demande de téléchargement Dropzone?

Je travaille sur une application d'une seule page et j'utilise Laravel 5 pour le service Web.

Tous les formulaires sont soumis de manière asynchrone et j'utilise un beforeSend sur eux pour attacher le jeton CSRF que je tire de la balise META comme suit:

$.ajax({
    url: '/whatever/route',
    type: 'POST',
    dataType: 'JSON',
    data: $('form#whatever-form').serialize(),
    beforeSend: function(request) {
        return request.setRequestHeader('X-CSRF-Token', $("meta[name='token']").attr('content'));
    },
    success: function(response){
        rivets.bind($('#whateverTag'), {whateverData: response});
    },
    error: function(response){
    }
});

Tous mes formulaires fonctionnent bien, mais le téléchargement par dropzone ne fonctionne pas. Cela me renvoie une exception TokenMismatchException. Voici mon code Dropzone pour mettre à jour la photo de profil:

$("#mydropzone").dropzone({
    url: "/profile/update-photo",
    addRemoveLinks : true,
    maxFilesize: 5,
    dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block visible-sm-block visible-lg-block"><span class="font-lg"><i class="fa fa-caret-right text-danger"></i> Drop files <span class="font-xs">to upload</span></span><span>&nbsp&nbsp<h4 class="display-inline"> (Or Click)</h4></span>',
    dictResponseError: 'Error uploading file!'
});

J'ai essayé de mettre la beforeSend ici aussi:

$("#mydropzone").dropzone({
    url: "/profile/update-photo",
    addRemoveLinks : true,
    maxFilesize: 5,
    dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block visible-sm-block visible-lg-block"><span class="font-lg"><i class="fa fa-caret-right text-danger"></i> Drop files <span class="font-xs">to upload</span></span><span>&nbsp&nbsp<h4 class="display-inline"> (Or Click)</h4></span>',
    dictResponseError: 'Error uploading file!',
    beforeSend: function(request) {
        return request.setRequestHeader('X-CSRF-Token', $("meta[name='token']").attr('content'));
    },
});

J'ai aussi essayé de mettre un ajaxSetup global dans mon fichier principal comme ceci:

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="token"]').attr('content')
    }
});

Cela ne fonctionne toujours pas. Qu'est-ce que je fais mal? Comment puis-je passer le jeton CSRF dans l'en-tête avec le téléchargement dropzone afin de ne pas obtenir une exception?

26
Rohan

Bon alors ce code fonctionne très bien maintenant:

$("#mydropzone").dropzone({
    url: "/profile/update-photo",
    addRemoveLinks : true,
    maxFilesize: 5,
    dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block visible-sm-block visible-lg-block"><span class="font-lg"><i class="fa fa-caret-right text-danger"></i> Drop files <span class="font-xs">to upload</span></span><span>&nbsp&nbsp<h4 class="display-inline"> (Or Click)</h4></span>',
    dictResponseError: 'Error uploading file!',
    headers: {
        'X-CSRF-TOKEN': $('meta[name="token"]').attr('content')
    }
});

Donc, fondamentalement, je devais ajouter le X-CSRFToken dans l'en-tête de la demande Dropzone. Fonctionne comme un charme maintenant.

42
Rohan

Vous pouvez ajouter un jeton csrf pour chaque requête jquery ajax dans votre application avec ce code.

$.ajaxSetup({
    headers: {
        'X-CSRF-Token': $('meta[name="_token"]').attr('content')
    }
});
7
Nyan Lynn Htut

Cela fonctionne aussi très bien:

$("#mydropzone").dropzone({
  url: "/profile/update-photo",
  addRemoveLinks : true,
  maxFilesize: 5,
  dictResponseError: 'Error uploading file!',
  headers: {
    'X-CSRF-Token': $('input[name="authenticity_token"]').val()
  }
});
3
Feuda

Je crois que le meilleur moyen de gérer cela est de le définir par défaut pour tous les messages ajax (avec jQuery), comme indiqué dans la documentation Django

https://docs.djangoproject.com/fr/1.8/ref/csrf/#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');

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

function sameOrigin(url) {
    // test that a given url is a same-Origin URL
    // url could be relative or scheme relative or absolute
    var Host = document.location.Host; // Host + port
    var protocol = document.location.protocol;
    var sr_Origin = '//' + Host;
    var Origin = protocol + sr_Origin;
    // Allow absolute or scheme relative URLs to same Origin
    return (url == Origin || url.slice(0, Origin.length + 1) == Origin + '/') ||
        (url == sr_Origin || url.slice(0, sr_Origin.length + 1) == sr_Origin + '/') ||
        // or any other URL that isn't scheme relative or absolute i.e relative.
        !(/^(\/\/|http:|https:).*/.test(url));
}

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
            // Send the token to same-Origin, relative URLs only.
            // Send the token only if the method warrants CSRF protection
            // Using the CSRFToken value acquired earlier
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

Dans votre exemple, vous avez une faute de frappe lorsque vous l'ajoutez au message ajax de Dropzone.js.

'X-CSRF-Token'

devrait être

'X-CSRFToken'

1
jb0t

Pour toute personne utilisant la configuration par défaut de Laravel:

window.Laravel = {!! json_encode([
    'csrfToken' => csrf_token(),
]) !!};

Dropzone.options.attachments = {
    url: 'upload',
    headers: {
        'X-CSRF-TOKEN': Laravel.csrfToken
    }
}
0
Steve Bauman

Nous pouvons définir le jeton CSRF dans l'en-tête de la demande.

 xhr = open("POST",logURL,true);
      //Set CSRF token in request header for prevent CSRF attack.
 xhr.setRequestHeader(CSRFHeaderName, CSRFToken);

0
kiran
you can add a headers.

var myDropzone = new Dropzone("#drop_id", {
    url: "/upload/",
    headers: {'x-csrftoken': $.cookie('csrftoken')},
    method:"post",  
    ...
}
0
liyufeng