如何在 Dropzone 上传请求的标头中包含 CSRF 令牌?
Posted
技术标签:
【中文标题】如何在 Dropzone 上传请求的标头中包含 CSRF 令牌?【英文标题】:How to include the CSRF token in the headers in Dropzone upload request? 【发布时间】:2015-07-20 20:33:45 【问题描述】:我正在开发一个单页应用程序,并且我正在使用 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 上传在标头中传递 CSRF 令牌,以免出现异常?
【问题讨论】:
您写了“Dropbox”,但我在您的问题中没有看到任何与 Dropbox 相关的内容。也许你的意思是说 Dropzone?我现在要删除 Dropbox 标签。 感谢您通知我。我真是太愚蠢了。 【参考方案1】:哇!惊人的反馈和建议!我对每条回复都做了一些处理,使其符合我的需要。
因此,让我将我现在使用 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>
【讨论】:
【参考方案2】:其他答案似乎都没有指出你首先需要将meta标签添加到你的布局刀片文件中,大概是因为默认刀片布局文件有它,但为了便于参考,可以添加如下:
<meta name="csrf-token" content=" csrf_token() ">
然后您可以在 Dropzone 调用的参数中引用 X-CSRF-TOKEN
标头:
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"
);
);
【讨论】:
【参考方案3】:Django 解决方案(感谢@Rohan):
headers:
'X-CSRFTOKEN': $('meta[name="token"]').context.cookie.split('=')[1]
,
【讨论】:
【参考方案4】:对于那些来到这里并正在寻找 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')
);
【讨论】:
【参考方案5】: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 */
);
);
你可以这样包含它。
【讨论】:
【参考方案6】:好的,这段代码现在可以正常工作了:
$("#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 请求的标头中添加X-CSRFToken
。现在像魅力一样工作。
【讨论】:
Dropzone 网站上的文档:dropzonejs.com/#config-headers 只是想稍微澄清一下命名,默认的 Laravel 安装正在寻找'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
。 laravel.com/docs/5.5/csrf#csrf-x-csrf-token
您能否编辑代码并将标头参数从X-CSRFToken
更改为X-CSRF-Token
。新人可能会花费很多时间来弄清楚这一点。
对于 Yii (php) 框架,当我在 Dropzone 配置中设置为 'X-CSRF-TOKEN'
或 'X-Csrf-Token'
并在服务器端读取为 $_SERVER['HTTP_X_CSRF_TOKEN']
时,它可以工作。但是如果我在 Dropzone 配置中设置为'X_CSRF_TOKEN'
,它不会显示在服务器端。只是一个注释,而不是抱怨。【参考方案7】:
you can add a headers.
var myDropzone = new Dropzone("#drop_id",
url: "/upload/",
headers: 'x-csrftoken': $.cookie('csrftoken'),
method:"post",
...
【讨论】:
是的,这与 OP 自己发布并接受的解决方案相同【参考方案8】:这也很好用:
$("#mydropzone").dropzone(
url: "/profile/update-photo",
addRemoveLinks : true,
maxFilesize: 5,
dictResponseError: 'Error uploading file!',
headers:
'X-CSRF-Token': $('input[name="authenticity_token"]').val()
);
【讨论】:
【参考方案9】:对于使用默认 Laravel 设置的任何人:
window.Laravel = !! json_encode([
'csrfToken' => csrf_token(),
]) !!;
Dropzone.options.attachments =
url: 'upload',
headers:
'X-CSRF-TOKEN': Laravel.csrfToken
【讨论】:
【参考方案10】:我们可以在请求头中设置 CSRF 令牌。
xhr = open("POST",logURL,true);
//Set CSRF token in request header for prevent CSRF attack.
xhr.setRequestHeader(CSRFHeaderName, CSRFToken);
【讨论】:
【参考方案11】:我相信处理这个问题的最好方法是根据 Django 文档为所有 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'
【讨论】:
将其设置为默认的 ajax 帖子会产生我稍后遇到的另一个问题。我试图使用第三方服务并卡住了,因为我无法理解错误是什么。后来我意识到,默认设置是向第三方发送 CSRF 令牌,这导致了问题。 :) 好点,值得记住!会说判断电话。如果您的代码中有更多的本地 ajax 调用,那么对远程调用进行异常处理可能更有意义,或者在相反的情况下反之。无论最终产生更少的工作。干杯!【参考方案12】:您可以使用这些代码为应用程序中的每个 jquery ajax 请求添加 csrf 令牌。
$.ajaxSetup(
headers:
'X-CSRF-Token': $('meta[name="_token"]').attr('content')
);
【讨论】:
根据the jQuery doc on this function,“不推荐使用它。”另外,我认为这可能只会影响通过 jQuery 库中的$.ajax()
进行的 AJAX 调用?以上是关于如何在 Dropzone 上传请求的标头中包含 CSRF 令牌?的主要内容,如果未能解决你的问题,请参考以下文章
AWS-amplify 在请求中包含 cognito Authorization 标头
是否可以在XMLHttpRequest标头中包含antiforgerytoken?
如何在 PHP 的 cURL POST HTTP 请求中包含授权标头?