Как включить токен CSRF Django 1.2 в HTML-форму, сгенерированную Javascript?

недавно я обновился до Django 1.2.3, и мои формы загрузки теперь сломаны. Всякий раз, когда я пытаюсь загрузить, я получаю " сбой проверки CSRF. Запрос прерван." сообщение об ошибке.

после прочтения документация Django по этому вопросу говорится, что мне нужно добавить тег шаблона {% csrf_token %} в HTML <form> в моем шаблоне. К сожалению, мой <form> генерируется с помощью JavaScript (в частности, свойство "html" ExtJs на Панель.)

короче говоря, как добавить требуемый тег токена CSRF в мой <form> когда моя <form> не входит в шаблон Django?

6 ответов


другой вариант-адаптировать решение на основе cookie / заголовка, показанное в документы Django С Ext-предпочтительнее, если у вас много шаблонов и вы не хотите менять каждый из них.

просто поместите следующий фрагмент в переопределения.js (или везде, где вы ставите глобальные модификации):

Ext.Ajax.on('beforerequest', function (conn, options) {
   if (!(/^http:.*/.test(options.url) || /^https:.*/.test(options.url))) {
     if (typeof(options.headers) == "undefined") {
       options.headers = {'X-CSRFToken': Ext.util.Cookies.get('csrftoken')};
     } else {
       options.headers.extend({'X-CSRFToken': Ext.util.Cookies.get('csrftoken')});
     }                        
   }
}, this);

(edit: Ext уже имеет функцию чтения файлов cookie, нет необходимости дублировать его)


самый простой способ-создать скрытую форму на Вашей странице с помощью django, которая ничего не делает. Затем используйте JavaScript для извлечения формы и, в частности, ввода токена из формы. Наконец, вставьте или скопируйте этот токен в форму, которую вы динамически генерируете.

вот два примера того, как вы можете опубликовать токен для JavaScript.

<input id="csrf_token" value="{{ csrf_token }}"/>

<script type="text/javascript">
var CSRF_TOKEN = document.getElementById('csrf_token').value;
</script>

или

<script type="text/javascript">
var CSRF_TOKEN = "{{ csrf_token }}";
</script>

лучшим решением является создание кода JS-файла из представления / шаблона.

затем в представлении вы можете установить токен csrf в контексте, например...

from django.core.context_processors import csrf
context = RequestContext(request)
context.update(csrf(request))

затем, в шаблоне можно использовать {{ csrf_token }} чтобы получить необработанное значение токена csrf, а затем использовать его для создания скрытого поля в вашей форме с именем csrfmiddlewaretoken.


делает вида POSTing также ответить на GET? В этом JS-код может сделать GET запрос к рассматриваемому представлению и анализ выходных данных для извлечения маркера CSRF. Мой JS-fu слаб, и я не уверен, как лучше всего вы можете сделать разбор со стороны клиента.

на широкое обзоры пример см. этот вопрос. В этом случае пользователь пытался POST использование скрипта Python и сбой по той же причине. Решение было то же самое, кроме того, что он должен был сделать это из скрипта Python, а не JavaScript.


это может быть не идеально, но это было самое быстрое решение для меня. В моем основном шаблоне в нижней части "тела" я добавил функцию javascript в свою библиотеку.

<script type="text/javascript">
    MyToolkit.Utils.getCSRFToken = function () {
         return "{% csrf_token %}";
    };
</script>

Это будет использовать токен csrf или автоматически генерировать новый, если это необходимо. Он будет обрабатывать все формы, представленные на странице. Если у вас есть формы вне сайта, Вам нужно убедиться, что они не запускают этот код.

<script>
$(document).on('submit', 'form[method=post]', function(){
  if(!document.cookie.match('csrftoken=([a-zA-Z0-9]{32})')) {
    for(var c = ''; c.length < 32;) c += 'abcdefghijklmnopqrstuvwxyz'.charAt(Math.random() * 26)
    document.cookie = 'csrftoken=' + c + '; path=/'
  }
  if(!this.csrfmiddlewaretoken) $(this).append('<input type="hidden" name="csrfmiddlewaretoken">')
  $(this.csrfmiddlewaretoken).val(document.cookie.match('csrftoken=([a-zA-Z0-9]{32})')[1])
})
</script>

требуется jQuery 1.7+