Как да включите CSRF токена в заглавките в заявката за качване в Dropzone?

Работя върху едностранично приложение и използвам Laravel 5 за уеб услугата.

Всички формуляри се изпращат асинхронно и аз използвам beforeSend върху тях, за да прикача CSRF токена, който вземам от мета тага така:

$.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){
    }
});

Всичките ми формуляри работят добре, но качването в dropzone не. Това ми връща TokenMismatchException изключение. Ето моя код за dropzone за актуализиране на профилната снимка:

$("#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 и тук:

$("#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'));
    },
});

Също така се опитах да поставя глобален ajaxSetup в основния си файл така:

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

Все още не работи. какво правя грешно Как мога да предам CSRF токена в заглавката с качването на dropzone, за да не получа изключение?


person Rohan    schedule 10.05.2015    source източник
comment
Написахте Dropbox, но не виждам нищо във въпроса ви, което да е свързано с Dropbox. Може би искахте да кажете Dropzone? Засега ще премахна етикета на Dropbox.   -  person user94559    schedule 10.05.2015
comment
Благодаря ви, че ми обърнахте внимание. Това беше толкова тъпо от моя страна.   -  person Rohan    schedule 10.05.2015


Отговори (9)


Добре, така че този код работи добре сега:

$("#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')
    }
});

Така че основно трябваше да добавя X-CSRFToken в заглавката на заявката за Dropzone. Сега работи като чар.

person Rohan    schedule 10.05.2015
comment
Документация на сайта на Dropzone: dropzonejs.com/#config-headers - person sameers; 22.12.2016
comment
просто исках да изясня малко именуването, инсталацията на Laravel по подразбиране търси 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'). laravel.com/docs/5.5/csrf#csrf-x-csrf- токен - person Andrew Brown; 18.09.2017
comment
Бихте ли могли да редактирате кода и да промените параметъра на заглавката от X-CSRFToken на X-CSRF-Token. Някой нов може да прекара много часове, за да разбере тази малка част. - person Eugene; 23.03.2018
comment
За Yii (PHP) рамката работи, когато задам като 'X-CSRF-TOKEN' или 'X-Csrf-Token' в конфигурацията на Dropzone и прочета като $_SERVER['HTTP_X_CSRF_TOKEN'] от страна на сървъра. Но ако задам като 'X_CSRF_TOKEN' в конфигурацията на Dropzone, това не се показва от страната на сървъра. Само бележка, без да се оплаквам. - person davneetnarang; 11.04.2019

Можете да добавите csrf токен за всяка jquery ajax заявка във вашето приложение с този код.

$.ajaxSetup({
    headers: {
        'X-CSRF-Token': $('meta[name="_token"]').attr('content')
    }
});
person Nyan Lynn Htut    schedule 11.05.2015
comment
Съгласно документа на jQuery за тази функция, използването й не се препоръчва. Освен това мисля, че това може да засегне само AJAX извикванията, направени чрез $.ajax() в библиотеката jQuery? - person sameers; 22.12.2016

Това също работи доста добре:

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

Dropzone.autoDiscover = false;
        // or disable for specific dropzone:
        // Dropzone.options.myDropzone = false;

        $(function () {
            // Now that the DOM is fully loaded, create the dropzone, and setup the
            // event listeners

            var myDropzone = new Dropzone("#my-awesome-dropzone");
            myDropzone.on("addedfile", function (file) {
                /* Maybe display some more file information on your page */
            });
            myDropzone.on("sending", function (file, xhr, formData) {
                 formData.append('csrfmiddlewaretoken', document.getElementsByName('csrfmiddlewaretoken')[0].value);
                /* Maybe display some more file information on your page */
            });
        });

Можете да го включите по този начин.

person Jeffrey Chidi    schedule 12.06.2019

Вярвам, че най-добрият начин да се справите с това е да го зададете по подразбиране за всички публикации на ajax (с jQuery), както според документите на Django

https://docs.djangoproject.com/en/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);
        }
    }
});

Във вашия пример имате правописна грешка, когато го добавяте към ajax публикацията на Dropzone.js.

„X-CSRF-токен“

би трябвало

„X-CSRFToken“

person jb0t    schedule 19.08.2015
comment
Задаването му на ajax публикации по подразбиране създава друг проблем, с който се сблъсках по-късно. Опитвах се да използвам услуга на трета страна и се забих, защото не можах да разбера каква е грешката. По-късно разбрах, че настройките по подразбиране са изпращали CSRF токена до третата страна и това е причинявало проблем. :) - person Rohan; 20.08.2015
comment
Добра гледна точка и си струва да се помни! Бих казал присъда. Ако имате много повече локални ajax повиквания във вашия код, тогава може би правенето на изключение за отдалечени повиквания би имало повече смисъл или обратното, когато е вярно обратното. Каквото и да е, в крайна сметка дава по-малко работа. наздраве! - person jb0t; 21.08.2015

За всеки, който използва настройката на Laravel по подразбиране:

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

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

Можем да зададем CSRF токен в заглавката на заявката.

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

person kiran    schedule 04.12.2015

За тези от вас, които са дошли тук и търсят решението на Rails, добавете заглавката със следния код:

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

Същото важи и за Laravel 6.x според документите: https://laravel.com/docs/6.x/csrf#csrf-x-csrf-token

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

person    schedule
comment
да, това е същото решение, което самият ОП публикува и прие - person nj2237; 05.05.2018