"Недопустимый токен CSRF или неправильный", а параметр post через AJAX в Django - программирование
Подтвердить что ты не робот

"Недопустимый токен CSRF или неправильный", а параметр post через AJAX в Django

Я пытаюсь опубликовать параметр, например

 jQuery.ajax(
        {
            'type': 'POST',
            'url': url,
            'contentType': 'application/json',
            'data': "{content:'xxx'}",
            'dataType': 'json',
            'success': rateReviewResult 
        }
    );

Однако Django возвращает Forbidden 403. CSRF verification failed. Request aborted. Я использую 'django.middleware.csrf.CsrfViewMiddleware' и не могу найти, как я могу предотвратить эту проблему без ущерба для безопасности.

4b9b3361

Ответ 1

Вы можете сделать AJAX-запрос двумя разными способами:

  1. Чтобы ваш взгляд не проверял токен csrf. Это можно сделать с помощью decorator @csrf_exempt, например так:

    from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def your_view_name(request):
        ...
    
  2. Чтобы встроить токен csrf в каждый запрос AJAX, для jQuery это может быть:

    $(function () {
        $.ajaxSetup({
            headers: { "X-CSRFToken": getCookie("csrftoken") }
        });
    });
    

    Где функция getCookie получает токен csrf из файлов cookie. Я использую следующую реализацию:

    function getCookie(c_name)
    {
        if (document.cookie.length > 0)
        {
            c_start = document.cookie.indexOf(c_name + "=");
            if (c_start != -1)
            {
                c_start = c_start + c_name.length + 1;
                c_end = document.cookie.indexOf(";", c_start);
                if (c_end == -1) c_end = document.cookie.length;
                return unescape(document.cookie.substring(c_start,c_end));
            }
        }
        return "";
     }
    

    Кроме того, jQuery имеет плагин для доступа к файлам cookie, что-то вроде этого:

    // set cookie
    $.cookie('cookiename', 'cookievalue');
    // read cookie
    var myCookie = $.cookie('cookiename');
    // delete cookie
    $.cookie('cookiename', null);
    

Ответ 2

Самый простой способ, который я нашел, - включить в данные значение {{csrf_token}}:

jQuery.ajax(
    {
        'type': 'POST',
        'url': url,
        'contentType': 'application/json',
        'data': {
            'content': 'xxx',
            'csrfmiddlewaretoken': '{{ csrf_token }}',
        },
        'dataType': 'json',
        'success': rateReviewResult 
    }
);

Ответ 3

Мне потребовалось некоторое время, чтобы понять, что делать с код, который отправил Даниэль. Но на самом деле все, что вам нужно сделать, это вставить его в начало файла javascript.

Для меня лучшим решением пока является:

  • Создайте csrf.js файл

  • Вставить код в файле csrf.js

  • Ссылка на код в нужном вам шаблоне

    <script type="text/javascript" src="{{ STATIC_PREFIX }}js/csrf.js"></script>
    

Обратите внимание, что STATIC_PREFIX/js/csrf.js указывает на мой файл. Я фактически загружаю переменную STATIC_PREFIX в {% get_static_prefix as STATIC_PREFIX %}.


Расширенный совет:, если вы используете шаблоны и имеете что-то вроде base.html, от которого вы расширяетесь, тогда вы можете просто ссылаться на script, и вам больше не нужно беспокоиться в остальном ваши файлы. Насколько я понимаю, это тоже не должно представлять проблемы безопасности.

Ответ 4

Простой и короткий

$.ajaxSetup({
  headers: { "X-CSRFToken": '{{csrf_token}}' }
});

ИЛИ ЖЕ

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
  beforeSend: function(xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", '{{csrf_token}}');
    }
  }
});

документы

Ответ 5

Спасибо всем за все ответы. Я использую Django 1.5.1. Я немного опаздываю на вечеринку, но здесь идет.

Я нашел ссылку на проект Django, чтобы быть очень полезной, но я действительно не хотел включать дополнительный код JavaScript каждый раз, когда я хотел сделать вызов Ajax.

Мне нравится ответ jerrykan, так как он очень краткий и добавляет только одну строку в обычный обычный вызов Ajax. В ответ на комментарии ниже его комментариев относительно ситуаций, когда теги шаблона Django недоступны, как насчет загрузки csrfmiddlewaretoken из DOM?

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    data: { 'csrfmiddlewaretoken': token },
    dataType: 'json',
    success: function(data) { console.log('Yippee! ' + data); } 
});

EDIT март 2016

Мой подход к этой проблеме за последние несколько лет изменился. Я добавляю код ниже (из Django docs) в файл main.js и загружаю его на каждую страницу. После этого вам не нужно будет беспокоиться о токере 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');

Ответ 6

Вчера у меня была такая же проблема, и я подумал, что это поможет людям, если есть простой способ справиться с этим, поэтому я написал для него плагин jQuery: jquery.djangocsrf. Вместо добавления токена CSRF в каждом запросе он сам перехватывает событие AjaxSend jQuery и добавляет куки файл клиента в заголовок.

Вот как это использовать:

1- включить его:

<script src="path/to/jquery.js"></script>
<script src="path/to/jquery.cookie.js"></script>
<script src="path/to/jquery.djangocsrf.js"></script>

2- включить его в свой код:

$.djangocsrf( "enable" );

Django всегда добавляет токен в файл cookie, если ваш шаблон использует {% csrf_token %}. Чтобы он всегда добавлял его, даже если вы не используете специальный тег в своем шаблоне, используйте декоратор @ensure_csrf_cookie:

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def my_view(request):
    return render(request, 'mytemplate.html')

Примечание: Im использует Django 1.6.2.

Ответ 7

Из-за отсутствия прямого ответа вам просто нужно добавить заголовок X-CSRFToken в запрос ajax, который находится в файле cookie csrftoken. JQuery не делает cookies (по какой-то причине) без плагин, поэтому:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>

и минимальное изменение кода:

$.ajax({
  headers: { "X-CSRFToken": $.cookie("csrftoken") },
  ...
});

Ответ 8

Включить заголовок x-csrftoken в запрос:

var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
jQuery.ajax({
    type: 'POST',
    url: url,
    beforeSend : function(jqXHR, settings) {
        jqXHR.setRequestHeader("x-csrftoken", get_the_csrf_token_from_cookie());
    },
    data: data,
    dataType: 'json',

});

Ответ 9

Самое быстрое решение без каких-либо плагинов, если вы не встраиваете js в шаблон:

Put <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script> <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script> перед ссылкой на файл script.js в шаблоне, затем добавьте csrfmiddlewaretoken в словарь data:

$.ajax({
            type: 'POST',
            url: somepathname + "do_it/",
            data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
            success: function() {
                console.log("Success!");
            }
        })

Если вы встраиваете свои js в шаблон, это просто: data: {csrfmiddlewaretoken: '{{ csrf_token }}'}

Ответ 10

Если после прочтения других ответов кто-то все еще борется, попробуйте следующее:

   $.ajax({
            type: "POST",
            beforeSend: function (request)
            {
                request.setRequestHeader("X-CSRF-TOKEN", "${_csrf.token}");
            },
            url: servlet_path,
            data : data,
            success : function(result) {
            console.log("Success!");
   }
});