我正在尝试创建一个将zip文件上传到服务器的表单。但是,每次我单击提交时,都会出现CSRF verification failed
错误。这是我的html代码:
<form method="POST" name="form-import-file" enctype="multipart/form-data">
<div>
<input type="file" id="file" name="file" accept=".zip"/>
<input type="submit" value="Upload file">
</div>
</form>
<div class="url-csrf" data-csrf="{{ csrf_token }}"></div>
<div class="url-import-file" data-url-import-file="{% url 'intent:import_file' %}"></div>
在我的.js代码中:
$("form[name='form-import-file']").submit(function(e) {
var formData = new FormData($(this)[0]);
alert(formData);
var json_data = {'csrfmiddlewaretoken' : $('.url-csrf').attr('data-csrf'), 'file': formData };
$.ajax({
url: $('.url-import-file').attr('data-url-import-file'),
type: "POST",
data: json_data,
success: function (msg) {
alert(msg)
},
cache: false,
contentType: false,
processData: false
});
e.preventDefault();
});
答案 0 :(得分:0)
{% csrf_token %}
是隐藏的输入字段,而不是value
以HTML格式
<div id="csrf_token">
{% csrf_token %}
</div>
在js中
let csrfToken = $("#csrf_token").val();
var json_data = {'csrfmiddlewaretoken' : csrfToken, 'file': formData };
答案 1 :(得分:0)
您尝试使用django doc提供的基于cookie的CSRF吗?
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 = cookies[i].trim();
// 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');
然后在您的json_data中添加'csrfmiddlewaretoken' : csrftoken,
答案 2 :(得分:0)
最好的方法可能是Django文档中描述的方法:Cross Site Request Forgery protection
如果您的CSRF_USE_SESSIONS
和CSRF_COOKIE_HTTPONLY
设置为False
,建议您创建init.js
文件,并始终将其加载到基本html模板中。在此文件中包括以下两个功能:
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;
}
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
};
要将CSRF令牌包含在ajax请求中,请使用以下代码将其包含在请求标头中:
$(document).ready(function () {
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
});
如果愿意,可以将此文件包含在先前创建的init.js
文件中,但必须在jQuery库之后加载。
如果您将CSRF_USE_SESSIONS
和CSRF_COOKIE_HTTPONLY
设置为True,请将{% csrf_token %}
添加到表单(或HTML中的其他位置),从那里读取令牌并将其包含在ajax中请求,例如这样:
var csrftoken = $("[name=csrfmiddlewaretoken]").val();
$.ajax({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
url: ...
...
...
});
答案 3 :(得分:0)
一个简单的解决方案是使用ensure_csrf_cookie
在呈现页面的视图中。重要的是,装饰器必须位于呈现页面的视图中,
不在收到post
请求的视图中。
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def get_the_page(request):
return render(request, 'template.html')