Javascript 如何在 Dropzone 上传请求的标头中包含 CSRF 令牌?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30149023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:44:25  来源:igfitidea点击:

How to include the CSRF token in the headers in Dropzone upload request?

javascriptlaravel-5csrfdropzone.js

提问by Rohan

I am working on a single page application and I am using Laravel 5 for the web service.

我正在开发一个单页应用程序,我使用 Laravel 5 作为 Web 服务。

All forms are submitted asynchronously and I use a beforeSend on them to attach the CSRF token which I take from the meta tag like so:

所有表单都是异步提交的,我在它们上使用 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){
    }
});

All my forms work fine but dropzone upload doesn't. It gives me back a TokenMismatchExceptionexception. Here is my dropzone code to update the profile photo:

我所有的表单都可以正常工作,但 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!'
});

I have tried putting the beforeSendin here too:

我也试过把它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'));
    },
});

I have also tried to put a global ajaxSetup in my main file like so:

我还尝试将全局 ajaxSetup 放在我的主文件中,如下所示:

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

It is still not working. What am I doing wrong? How can I pass the CSRF token in the header with the dropzone upload so as to not a get an exception?

它仍然无法正常工作。我究竟做错了什么?如何通过 dropzone 上传在标头中传递 CSRF 令牌,以免出现异常?

回答by Rohan

Okay so this code is working just fine now:

好的,所以这段代码现在工作得很好:

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

So basically I needed to add the X-CSRFTokenin the header of the Dropzone request. Works like charm now.

所以基本上我需要X-CSRFToken在 Dropzone 请求的标头中添加。现在像魅力一样工作。

回答by Nyan Lynn Htut

You can add csrf token for every jquery ajax request within your application with these code.

您可以使用这些代码为应用程序中的每个 jquery ajax 请求添加 csrf 令牌。

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

回答by Feuda

This also works pretty well :

这也很有效:

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

回答by Jeffrey Chidi

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

You could include it this way.

你可以这样包含它。

回答by jb0t

I believe the best way to handle this is to set it by default for all ajax posts (with jQuery) as according to the Django docs

我相信处理这个问题的最好方法是根据 Django 文档为所有 ajax 帖子(使用 jQuery)默认设置它

https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax

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

In your example, you have a typo when adding it to the Dropzone.js ajax post.

在您的示例中,将其添加到 Dropzone.js ajax 帖子时您有一个错字。

'X-CSRF-Token'

'X-CSRF-Token'

should be

应该

'X-CSRFToken'

'X-CSRFToken'

回答by kiran

We can set CSRF token in request header.

我们可以在请求头中设置 CSRF 令牌。

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

回答by Steve Bauman

For anyone using default Laravel setup:

对于使用默认 Laravel 设置的任何人:

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

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

回答by Paulo Fidalgo

For those of you that came here and are looking for the Rails solution, add the header with the following code:

对于那些来到这里并正在寻找 Rails 解决方案的人,请使用以下代码添加标题:

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

The same applies for Laravel 6.x according to the docs: https://laravel.com/docs/6.x/csrf#csrf-x-csrf-token

根据文档,这同样适用于 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')
    }
});

回答by liyufeng

you can add a headers.

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