Как я могу решить, проверка CSRF не удалось - PullRequest
0 голосов
/ 26 апреля 2019

Я пытаюсь создать форму, которая загружает 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 голосов
/ 26 апреля 2019

Простым решением является использование sure_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')

0 голосов
/ 26 апреля 2019

Пробовали ли вы использовать CSRF на основе файлов cookie, предоставленный django doc?

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

Затем добавьте 'csrfmiddlewaretoken' : csrftoken, в вас json_data

0 голосов
/ 26 апреля 2019

Наилучшим подходом, вероятно, является описанный в документации Django: Защита от подделки межсайтовых запросов

Если ваши 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: ...
    ...
    ...
});
0 голосов
/ 26 апреля 2019

{% csrf_token %} скрытое поле ввода, а не value

В HTML

<div id="csrf_token">
    {% csrf_token %}
</div>

В js

let csrfToken = $("#csrf_token").val();
var json_data = {'csrfmiddlewaretoken' : csrfToken, 'file': formData };
...