11

我最近升级到 Django 1.2.3,我的上传表单现在坏了。每当我尝试上传时,我都会收到“CSRF 验证失败。请求中止”。错误信息。

在阅读了Django关于这个主题的文档后,它指出我需要<form>在我的模板的 HTML 中添加 {% csrf_token %} 模板标签。不幸的是,my<form>是通过 JavaScript 生成的(特别是面板上 ExtJs 的“html”属性)。

长话短说,<form>当我<form>不包含在 Django 模板中时,如何将所需的 CSRF 令牌标签添加到我的?

4

6 回答 6

13

另一种选择是使用 Ext调整 Django 文档中显示的基于 cookie/header 的解决方案- 如果您有很多模板并且不想更改每一个模板,则更可取。

只需将以下代码段放入您的 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读取功能,无需复制)

于 2011-03-30T11:22:04.347 回答
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>
于 2010-09-21T21:29:32.323 回答
1

更好的解决方案是从视图/模板生成 js 文件的代码。

然后,在视图中,您可以像这样在上下文中设置 csrf 令牌......

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

然后,在模板中,您可以使用{{ csrf_token }}获取 csrf 令牌的原始值,然后使用它在表单中构建一个名为 的隐藏字段csrfmiddlewaretoken

于 2010-11-10T12:23:07.543 回答
0

你要回应的观点是否POST也有回应GET?因为 JS 代码可以GET向相关视图发出请求并解析输出以提取 CSRF 令牌。我的 JS-fu 很弱,我不确定从客户端进行解析的效果如何。

有关广泛相关的示例,请参见此问题。在这种情况下,用户尝试POST使用 Python 脚本并由于同样的原因而失败。解决方案是相同的,只是他必须使用 Python 脚本而不是 JavaScript。

于 2010-09-22T05:13:34.587 回答
0

这可能并不理想,但对我来说这是最快的解决方案。在“正文”底部的主模板中,我向我的库中添加了一个 javascript 函数。

<script type="text/javascript">
    MyToolkit.Utils.getCSRFToken = function () {
         return "{% csrf_token %}";
    };
</script>
于 2011-10-12T16:06:59.200 回答
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+

于 2014-01-24T18:05:38.623 回答