我最近升级到了Django 1.2.3,我的上传表单现在已经破了。每当我尝试上传时,都会收到“CSRF验证失败。请求中止”。错误信息。
在阅读有关此主题的Django's documentation后,它指出我需要在模板中的HTML <form>
中添加{%csrf_token%}模板标记。不幸的是,我的<form>
是通过JavaScript生成的(具体来说,是Panel上ExtJs的“html”属性)。
简而言之,当我的<form>
未包含在Django模板中时,如何将所需的CSRF令牌标记添加到<form>
?
答案 0 :(得分:13)
另一种选择是使the Django docs中显示的基于cookie / header的解决方案与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读取功能,无需复制)
答案 1 :(得分:9)
最简单的方法是使用不执行任何操作的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>
答案 2 :(得分:1)
更好的解决方案是从视图/模板生成js文件的代码。
然后,在视图中,您可以在上下文中设置csrf标记,如此...
from django.core.context_processors import csrf
context = RequestContext(request)
context.update(csrf(request))
然后,在模板中,您可以使用{{ csrf_token }}
获取csrf令牌的原始值,然后使用它在表单中构建一个名为csrfmiddlewaretoken
的隐藏字段。
答案 3 :(得分:0)
您POST
的观点是否也会回复GET
?因为JS代码可以对有问题的视图发出GET
请求,并解析输出以提取CSRF令牌。我的JS-fu很弱,我不确定你能从客户端做出最好的解析。
对于广泛相关示例,请参阅this question。在这种情况下,用户尝试POST
使用Python脚本并因同样的原因失败。解决方案是相同的,除了他必须从Python脚本而不是JavaScript。
答案 4 :(得分:0)
这可能不太理想,但对我来说这是最快的解决方案。在我的主体模板“body”的底部,我向我的库中添加了一个javascript函数。
<script type="text/javascript">
MyToolkit.Utils.getCSRFToken = function () {
return "{% csrf_token %}";
};
</script>
答案 5 :(得分:0)
如果需要,这将使用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 +