多个模板的 csrf 令牌问题

Posted

技术标签:

【中文标题】多个模板的 csrf 令牌问题【英文标题】:csrf token issue with multiple templates 【发布时间】:2014-12-29 10:03:38 【问题描述】:

我有一个模板(index.html。它扩展了 base.html),其中包含一个带有 csrf_token 的表单,效果很好。我使用 JS/Ajax 将数据发送到我的视图。所以没问题。

问题是,如果我将表单复制/粘贴到另一个模板(例如:new.html,它也扩展了 base.html),我会得到:CSRF 令牌丢失或错误错误。 (控制台出现 HTTP 403 错误)

两个模板使用相同的 JS 函数。两个模板中的表单完全相同。

有什么建议吗?

这里的表单(index.html 和 new.html 相同):

<form method="post" action="." enctype="multipart/form-data">
% csrf_token %
    <a href="#" class="heart pull-right" onclick="return Favorite(this)" data="foobar">
        <i class="fa fa-heart-o"></i>
    </a>
</form>

这里是 JS/Ajax 函数:

function Favorite(item) 
    song_id = item.getAttribute("data"),
    $.ajax(
        type : "POST",
        datatype: "json",
        url: "/fav/",
        data: 
            'csrfmiddlewaretoken' : $('input[name=csrfmiddlewaretoken]').val(),
            song_id : song_id
        ,
    );
    return false

顺便说一下,index.html 中的表单是在一个 div 中。在 new.html 中,表单位于表格中。不知道有没有帮助。

【问题讨论】:

显示new.html 只是一个sn-p,您正在使用该表单。还有JS 函数。 您需要更多信息吗? 先检查token是否通过?在您的 JS 函数 alert 或写入 console.log 的值 $('input[name=csrfmiddlewaretoken]').val() 例如alert($('input[name=csrfmiddlewaretoken]').val()); 返回index.html模板中的token值。但它在 new.html 模板中返回“未定义” @NabIlovich 很明显,您的 csrf 选择器是错误的!或者 new.html 中没有输入字段 【参考方案1】:

首先,如果您使用 ajax 发送请求,则根本不需要 &lt;form&gt;

其次,你也可以这样设置csrf_token

...
data: 
    csrfmiddlewaretoken: ' csrf_token ',
    song_id : song_id
,
...

这对我总是有效的。

【讨论】:

我删除了表单并尝试了您的代码但没有结果:/。我仍然遇到 403 问题。 @NabIlovich 你用的是什么版本的 django? @NabIlovich 只需复制此文件,将其保存到单独的 js 文件中,然后将其导入您的 base.html 到顶部。 pastebin.com/u7vbfDMK Django 1.7 和 python 3.4 如果我理解你的脚本,它会从 cookie 中读取 csrf 令牌,对吗? (我是开发新手)。我添加了它,但没有结果。【参考方案2】:

我终于成功了(基于 django doc 和 doniyor cmets)

function getCookie(name) 
var cookieValue = null;
if (document.cookie && document.cookie != '') 
    var cookies = document.cookie.split(';');
    for (var i = 0; i < cookies.length; i++) 
        var cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) == (name + '=')) 
            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
            break;
        
    

return cookieValue;


function Favorite(item) 
  song_id = item.getAttribute("data-mp3"),
  csrftoken = getCookie('csrftoken');
  $.ajax(
    type : "POST",
    datatype: "json",
    url: "/fav/",
    data: 
      song_id : song_id
    ,
    headers: 
      'X-CSRFToken': csrftoken
    
  );
  return false;

【讨论】:

以上是关于多个模板的 csrf 令牌问题的主要内容,如果未能解决你的问题,请参考以下文章

没有表单的 Django CSRF 令牌

无模板 Django + AJAX:Django 的 CSRF 令牌是不是在浏览会话过程中更新?

spring security 3.2.0 csrf 令牌在 freemarker 模板中不起作用

一个令牌与多个令牌以防止 CSRF 攻击

Zend Form - 一页中的多个表单和(CSRF)令牌验证

每个请求的 Csrf 令牌 [关闭]