如何在 Dropzone 上传请求中的 headers 中包含 CSRF 令牌?
How to include the CSRF token in the headers in Dropzone upload request?
我正在开发一个单页应用程序,我正在使用 Laravel 5 作为 Web 服务。
所有表单都是异步提交的,我在它们上使用 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>  <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>  <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')
}
});
还是不行。我究竟做错了什么?如何通过 dropzone 上传在 header 中传递 CSRF 令牌,以免出现异常?
好的,这段代码现在可以正常工作了:
$("#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>  <h4 class="display-inline"> (Or Click)</h4></span>',
dictResponseError: 'Error uploading file!',
headers: {
'X-CSRF-TOKEN': $('meta[name="token"]').attr('content')
}
});
所以基本上我需要在 Dropzone 请求的 header 中添加 X-CSRFToken
。现在像魅力一样工作。
您可以使用这些代码为应用程序中的每个 jquery ajax 请求添加 csrf 令牌。
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="_token"]').attr('content')
}
});
我相信处理这个问题的最好方法是根据 Django 文档
为所有 ajax posts(使用 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 post.
时出现错字
'X-CSRF-Token'
应该是
'X-CSRFToken'
我们可以在请求头中设置CSRF token。
xhr = open("POST",logURL,true);
//Set CSRF token in request header for prevent CSRF attack.
xhr.setRequestHeader(CSRFHeaderName, CSRFToken);
对于使用默认 Laravel 设置的任何人:
window.Laravel = {!! json_encode([
'csrfToken' => csrf_token(),
]) !!};
Dropzone.options.attachments = {
url: 'upload',
headers: {
'X-CSRF-TOKEN': Laravel.csrfToken
}
}
这也很好用:
$("#mydropzone").dropzone({
url: "/profile/update-photo",
addRemoveLinks : true,
maxFilesize: 5,
dictResponseError: 'Error uploading file!',
headers: {
'X-CSRF-Token': $('input[name="authenticity_token"]').val()
}
});
you can add a headers.
var myDropzone = new Dropzone("#drop_id", {
url: "/upload/",
headers: {'x-csrftoken': $.cookie('csrftoken')},
method:"post",
...
}
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 */
});
});
你可以这样包含它。
对于那些来到这里并正在寻找 Rails 解决方案的人,请使用以下代码添加 header:
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')
}
});
Django 解决方案(感谢@Rohan):
headers: {
'X-CSRFTOKEN': $('meta[name="token"]').context.cookie.split('=')[1]
},
None 的其他答案似乎指出您首先需要将元标记添加到您的布局 blade 文件中,大概是因为默认的 blade 布局文件有它,但为了方便参考,可以添加如下:
<meta name="csrf-token" content="{{ csrf_token() }}">
然后您可以在 Dropzone 调用的参数中引用 X-CSRF-TOKEN
header:
Dropzone.autoDiscover = false;
jQuery(document).ready(function($) {
$("div#uploader").dropzone({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
paramName: 'attachment',
url: "/upload/path"
});
});
哇!惊人的反馈和建议!我对每一个回复都做了一点修改,使之符合我的需要。
因此,让我 pass-it-forward 使用我现在使用 Flask-WTF 和“X-CSRF-Token”Dropzone Header 用于我的 FLASK 服务器的代码。
<form>
<div class="form-horizontal">
<div class="upload-drop-zone" id="drop-zone-licenseKey">
<div class="dz-message">
Drag and Drop, or Click to<br> enter your new license key
</div>
</div>
<script>
var uploadLicenseKey = new Dropzone("div#drop-zone-licenseKey",{
init: function()
{
// Do Stuff
},
url: "/myLicenseURL",
paramName: "myKey",
maxFilesize: 1, //MB,
maxFiles: 1,
uploadMultiple: false,
addRemoveLinks: true,
autoProcessQueue: false, // do not upload until save is pressed
acceptedFiles: ".txt",
headers: { "X-CSRF-Token" : "{{ csrf_token() }}" }
});
</script>
</div>
我正在开发一个单页应用程序,我正在使用 Laravel 5 作为 Web 服务。
所有表单都是异步提交的,我在它们上使用 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>  <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>  <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')
}
});
还是不行。我究竟做错了什么?如何通过 dropzone 上传在 header 中传递 CSRF 令牌,以免出现异常?
好的,这段代码现在可以正常工作了:
$("#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>  <h4 class="display-inline"> (Or Click)</h4></span>',
dictResponseError: 'Error uploading file!',
headers: {
'X-CSRF-TOKEN': $('meta[name="token"]').attr('content')
}
});
所以基本上我需要在 Dropzone 请求的 header 中添加 X-CSRFToken
。现在像魅力一样工作。
您可以使用这些代码为应用程序中的每个 jquery ajax 请求添加 csrf 令牌。
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="_token"]').attr('content')
}
});
我相信处理这个问题的最好方法是根据 Django 文档
为所有 ajax posts(使用 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 post.
时出现错字'X-CSRF-Token'
应该是
'X-CSRFToken'
我们可以在请求头中设置CSRF token。
xhr = open("POST",logURL,true);
//Set CSRF token in request header for prevent CSRF attack.
xhr.setRequestHeader(CSRFHeaderName, CSRFToken);
对于使用默认 Laravel 设置的任何人:
window.Laravel = {!! json_encode([
'csrfToken' => csrf_token(),
]) !!};
Dropzone.options.attachments = {
url: 'upload',
headers: {
'X-CSRF-TOKEN': Laravel.csrfToken
}
}
这也很好用:
$("#mydropzone").dropzone({
url: "/profile/update-photo",
addRemoveLinks : true,
maxFilesize: 5,
dictResponseError: 'Error uploading file!',
headers: {
'X-CSRF-Token': $('input[name="authenticity_token"]').val()
}
});
you can add a headers.
var myDropzone = new Dropzone("#drop_id", {
url: "/upload/",
headers: {'x-csrftoken': $.cookie('csrftoken')},
method:"post",
...
}
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 */
});
});
你可以这样包含它。
对于那些来到这里并正在寻找 Rails 解决方案的人,请使用以下代码添加 header:
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')
}
});
Django 解决方案(感谢@Rohan):
headers: {
'X-CSRFTOKEN': $('meta[name="token"]').context.cookie.split('=')[1]
},
None 的其他答案似乎指出您首先需要将元标记添加到您的布局 blade 文件中,大概是因为默认的 blade 布局文件有它,但为了方便参考,可以添加如下:
<meta name="csrf-token" content="{{ csrf_token() }}">
然后您可以在 Dropzone 调用的参数中引用 X-CSRF-TOKEN
header:
Dropzone.autoDiscover = false;
jQuery(document).ready(function($) {
$("div#uploader").dropzone({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
paramName: 'attachment',
url: "/upload/path"
});
});
哇!惊人的反馈和建议!我对每一个回复都做了一点修改,使之符合我的需要。
因此,让我 pass-it-forward 使用我现在使用 Flask-WTF 和“X-CSRF-Token”Dropzone Header 用于我的 FLASK 服务器的代码。
<form>
<div class="form-horizontal">
<div class="upload-drop-zone" id="drop-zone-licenseKey">
<div class="dz-message">
Drag and Drop, or Click to<br> enter your new license key
</div>
</div>
<script>
var uploadLicenseKey = new Dropzone("div#drop-zone-licenseKey",{
init: function()
{
// Do Stuff
},
url: "/myLicenseURL",
paramName: "myKey",
maxFilesize: 1, //MB,
maxFiles: 1,
uploadMultiple: false,
addRemoveLinks: true,
autoProcessQueue: false, // do not upload until save is pressed
acceptedFiles: ".txt",
headers: { "X-CSRF-Token" : "{{ csrf_token() }}" }
});
</script>
</div>