Как включить токен CSRF Django 1.2 в HTML-форму, сгенерированную Javascript? - PullRequest
10 голосов
/ 22 сентября 2010

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

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

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

Ответы [ 6 ]

13 голосов
/ 30 марта 2011

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

Просто добавьте следующий фрагмент в ваш файл overrides.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);

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

9 голосов
/ 22 сентября 2010

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

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

1 голос
/ 10 ноября 2010

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

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

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

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

0 голосов
/ 24 января 2014

Это будет использовать токен 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 +

0 голосов
/ 12 октября 2011

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

<script type="text/javascript">
    MyToolkit.Utils.getCSRFToken = function () {
         return "{% csrf_token %}";
    };
</script>
0 голосов
/ 22 сентября 2010

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

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

...