2013-03-30 8 views
0

Я продолжаю получать 403 ошибки из Django.Django/JQuery CSRF: 403 Ошибка

Я установил свои settings.py для использования защиты CSRF и использовал токен csrf_token в своем шаблоне.

Вот файл JS я включил только после HTML заголовка: http://bpaste.net/show/87791/

Использование Firebug я могу проверить, что печенье CSRF есть. Позже на странице, пользователь нажимает на кнопку, которая запускает этот код:

myFunction: function() { 
    $.ajax({ 
    type: 'POST', 
    url: window.localtion.href + 'myajaxview', 
    async: false 
    }); 
} 

Я использую на основе простой вид класса, унаследованный от TemplateView, чтобы отобразить страницу. «myajaxview» наследуется от View и JSON Mixin. Однако его код никогда не выполняется, поскольку django не может проверить токен CSRF.

Мне кажется, что ajax не отправляет токен с заголовками POST, как должен. Или я чего-то не хватает?

EDIT: Я переехал вызов $ .ajaxSetup непосредственно перед вызовом функции $ .ajax() POST, и это сработало. Я попытался переместить его в другое место, и это не удалось. Я думаю, проблема связана скорее с Ajax, чем с Django. Итак, мой вопрос по-прежнему существует, я не хочу ставить вызов $ .ajaxSetup перед каждым вызовом $ .ajax, я не думаю, что так оно и делается, я не хочу повторять сам. Так что это было всего лишь обходным путем, и я прошу разрешения.

+0

Вы можете взглянуть на csrf_exempt [здесь] (https://docs.djangoproject.com/en/1.2/ref/contrib/csrf/) –

+0

Уже видел, что если вы посмотрите на мой код на bpaste, это почти то же самое. Разница в том, что я включаю это как внешний .js-файл. Поскольку я хочу поделиться этой функцией и не включать один и тот же код каждый раз, когда я делаю запрос ajax в каждом шаблоне. Может, в этом и проблема? Где поставить csrf_token при использовании ajax? И где поставить код getCookie (т. Е. Только если я сделал это неправильно)? – Aki

ответ

0

Благодарим за помощь. Ответ действительно противный, я нашел его, начав с простого примера, чтобы проверить ajaxSetup + ajax, а затем добавил дополнительную сложность в соответствие с моим исходным кодом.

Это было из-за jquery-tools. Когда я начал использовать bootstrap-twitter, я увидел, что они советуют включить javascript в конце страницы. Поэтому я включил jquery-tools.js. Мало ли я знал, что в этом файле сценария был сделан вызов $ .ajaxSetup, который перевернул мой собственный.

Решение состоит в том, чтобы включить jquery-инструменты на верхнем уровне. Однако на данный момент я не уверен, насколько это будет противоречить моему коду. Поскольку мне нужен ajaxSetup для каждого запроса ajax, я сделаю.

Мне потребовался день, чтобы узнать, я был на #jquery и #django, и многие люди ушли с дороги, чтобы попытаться найти решение. Если вы когда-либо получаете сложную базу кода, которую вы не можете поделиться, и проблема, которую вы хотите решить, вот мой совет: попробуйте сделать простейший пример работы и изменить его, пока он не соответствует вашей неудачной настройке. Это спасет все время, прежде всего ваше собственное.

0

Во-первых, вы проверили, действительно ли код CSRF отправляется на сервер? Если это так, ожидает ли сервер хеш в значениях post или в заголовке? Прямо сейчас вы устанавливаете заголовок запроса. Если оба не решили проблему, проверьте, знает ли сервер правильный хэш. Когда клиент отправляет правильный хеш, а сервер имеет NULL как хэш, тогда проверка не завершится.

+0

Код csrf находится в файлах cookie. Но согласно JS-коду, он должен быть в заголовках запросов, это не так. Поэтому я бы сказал, что код CSRF не отправляется на сервер, это то, что я подозревал, но я не знаю почему. – Aki

+0

Вы подтвердили наличие cookie 'csrftoken'? – f4der

+0

Он присутствует на веб-странице и в файлах cookie. Но не в HTTP-заголовке для запроса POST. Я обновил свой вопрос с дополнительной информацией. – Aki

2

Это фрагмент кода, который я думаю, что вы ищете

var csrfToken = $('input[name="csrfmiddlewaretoken"]').val(); 
$.ajax({ 
    url: 'blah.com/', 
    //snipped for brevity 
    csrfmiddlewaretoken: csrfToken, 
    success: function(data){ doStuff(); } 
}); 

Это то, что я использую для того, чтобы иметь возможность сделать JQuery Ajax звонки в приложение Джанго. Надеюсь, это сработает!

+0

Я ценю это. Я могу использовать getCookie() вместо вашего метода, чтобы правильно получить csrfToken? Но все же я озадачен тем, почему xfer.setRequestHeader() не работает в beforeSend(). Если я заработаю, то мне не нужно вручную добавлять csrfmiddlewaretoken. – Aki

+0

Вы можете использовать его, чтобы получить токен csrf, но установка xhr.beforesend не работает для меня. Я считаю, что это связано с тем, что csrf_token генерируется неправильно при использовании динамически загружаемых форм или элементов dom. Я рассмотрю его позже сегодня и предоставит вам обновление. –

+0

Похоже, что это не сработало, хотя оно находится в официальной документации django. Я думаю, я нашел решение, чтобы заставить его работать, но я не уверен, что я решил проблему каждого, так как мой был конкретным. – Aki

3
myFunction: function() { 
    $.ajax({ 
    type: 'POST', 
    data: { 
    'csrfmiddlewaretoken': '{{csrf_token}}' 
    }, 
    url: '/myajaxview/', 
    async: false 
    }); 
} 
+0

Это как ответ limelights, он работает, я думаю, и буду помогать другим, но я стараюсь делать это так, как говорит документация: на каждом XMLHttpRequest установите собственный заголовок X-CSRFToken на значение токена CSRF. Вот почему я борюсь с beforeSend() .. – Aki

+0

Ну, это работает сейчас. Я считаю, что самая сложная задача - обеспечить, чтобы beforeSend() не переопределялась библиотекой, особенно при использовании async. Но теперь это работает для меня (см. Мой ответ). Спасибо за ваш вклад, хотя я могу использовать его в некоторых сценариях! – Aki

0

Я решил проблему, вычислив значение для токена, когда DOM готов, и AJAX перезагружается.

Код javascript использует функцию reload_ajax() для обработки токена, а также любые другие вещи, которые необходимо обновить как на начальной загрузке страницы, так и на последующих вызовах AJAX.

<script type="text/javascript"> 

function reload_ajax() { 
    // Useful on initial page load, and after calling AJAX. 
    $("input#token").val("{{ csrf_token }}"); 
} 

$(document).ready(function() { 
    $("form#stats").unbind("submit");  // Prevents calling document-ready multiple times 
    $("form#stats").submit(function(event) { 
     event.preventDefault(); 
     $.ajax({ 
      type:"POST", 
      url: $(this).attr("action"), 
      data: $(this).serialize(),  // Serialize the form 
      dataType: "json", 
      success: function(response){ 
       $("#stats_ajax").html(response.html); // Object to refresh after AJAX 
       reload_ajax(); 
      } 
     }); 
     return false; 
    }); 

    reload_ajax(); 
}); 
</script> 

Я использую два HTML-файлы, В main.html, у меня есть яваскрипт кода, приведенного выше, а также следующее:

<div id="stats_ajax"> 
    {% include "stats_ajax.html" %} 
</div> 

В stats_ajax.html, у меня есть конкретный вид (а также другие вещи, мне нужно обновить)

<form id="stats" action="/main/" method="post"> 
    <!-- The value will be inserted when the DOM reloads. --> 
    <input id="token" type="hidden" name="csrfmiddlewaretoken" value="" /> 
    <!-- Other input elements --> 
    <button type="submit">Submit</button> 
</form> 

в моей views.py файле

# Not all imports may be needed for this example 
from django.http import HttpResponse 
from django.shortcuts import render, redirect 
from django.template.loader import render_to_string 
import json 

def main(request): 
    # This request should only be posting AJAX 
    if request.is_ajax(): 
     data = {} 
     data["message"] = "Awesome" 
     # This is the template to load on the DOM object to update 
     html = render_to_string("stats_ajax.html", data) 
     res = {"html": html} 
     return HttpResponse(json.dumps(res), mimetype='application/json') 

    # Handle GET to this view 
    return redirect("/main") 

Наконец, мой urls.py имеет

# Replace "application_name" with your own value 
url(r'^main', 'application_name.views.main'), 
+0

сделал все как вы, но ошибка ((Запрещено (403) Не удалось выполнить проверку CSRF. Запрос прерван. "GET/main HTTP/1.1" 200 1111 "POST/main HTTP/1.1" 403 2294 – Olga

Смежные вопросы