Как включить Django 1.2 CSRF-токен в HTML-форму, сгенерированную Javascript?
Недавно я обновился до Django 1.2.3, и мои загружаемые формы теперь сломаны. Всякий раз, когда я пытаюсь загрузить, я получаю "CSRF проверка не удалась. Запрос прерван". сообщение об ошибке.
После прочтения документации Django по этому вопросу, в нем говорится, что мне нужно добавить тег шаблона {% csrf_token%} в HTML <form>
в моем шаблоне. К сожалению, мой <form>
создается через JavaScript (в частности, свойство "html" ExtJs на панели).
Короче говоря, как добавить тег токена CSRF в мой <form>
, когда мой <form>
не включен в шаблон Django?
Ответы
Ответ 1
Другой вариант - адаптировать решение на основе 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);
(edit: Ext уже имеет функцию чтения файлов cookie, не нужно ее дублировать)
Ответ 2
Самый простой способ - создать скрытую форму на вашей странице, используя 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>
Ответ 3
Лучшим решением является генерация кода js файла из представления/шаблона.
Затем в представлении вы можете установить токен csrf в контекст, например...
from django.core.context_processors import csrf
context = RequestContext(request)
context.update(csrf(request))
Затем в шаблоне вы можете использовать {{ csrf_token }}
, чтобы получить исходное значение токена csrf, а затем использовать его для создания скрытого поля в вашей форме с именем csrfmiddlewaretoken
.
Ответ 4
Представляет ли ваше мнение POST
ing также отвечать на GET
? В этом случае код JS может сделать запрос GET
рассматриваемому представлению и проанализировать вывод для извлечения маркера CSRF. Мой JS-fu слаб, и я не уверен, как лучше всего вы можете разобрать партию с клиентской стороны.
Для широко связанного примера см. этот вопрос. В этом случае пользователь пытался выполнить POST
с помощью Python script и не смог по той же причине. Решение было таким же, за исключением того, что он должен был сделать это из Python script, а не из JavaScript.
Ответ 5
Это может быть не идеальным, но это было самым быстрым решением для меня. В моем основном шаблоне в нижней части "тела" я добавил функцию javascript в свою библиотеку.
<script type="text/javascript">
MyToolkit.Utils.getCSRFToken = function () {
return "{% csrf_token %}";
};
</script>
Ответ 6
При этом будет использоваться токен 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 +