如何解决CSRF验证失败

时间:2019-04-26 08:58:47

标签: ajax django django-csrf

我正在尝试创建一个将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();
});

4 个答案:

答案 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_SESSIONSCSRF_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_SESSIONSCSRF_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')