web-dev-qa-db-ja.com

DropzoneアップロードリクエストのヘッダーにCSRFトークンを含める方法

私は単一ページのアプリケーションに取り組んでおり、Webサービスに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){
    }
});

すべてのフォームは正常に機能しますが、ドロップゾーンのアップロードは機能しません。 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トークンを渡すにはどうすればよいですか?

30
Rohan

わかりましたので、このコードは今うまく動作しています:

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

そのため、基本的にDropzoneリクエストのヘッダーにX-CSRFTokenを追加する必要がありました。今魅力のように動作します。

46
Rohan

これらのコードを使用して、アプリケーション内のjquery ajaxリクエストごとにcsrfトークンを追加できます。

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

これもかなりうまくいきます:

$("#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

これを処理する最良の方法は、Django docsに従って、すべてのajax投稿(jQueryを使用)に対してデフォルトで設定することです。

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);
        }
    }
});

この例では、Dropzone.js ajax投稿に追加するときにタイプミスがあります。

「X-CSRF-Token」

あるべき

「X-CSRFToken」

1
jb0t
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 */
            });
        });

この方法で含めることができます。

1
Jeffrey Chidi

デフォルトLaravel setupを使用している場合:

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

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

要求ヘッダーにCSRFトークンを設定できます。

 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