如何将csrf_token传递给jqGrid的editurl的post参数?

4 投票
4 回答
4687 浏览
提问于 2025-04-16 20:15

我正在使用JqGrid和Django框架。这是一些JavaScript代码:

      jQuery("#list").jqGrid({
        url:'{% url views.manage.devicesajax %}',
        datatype: 'json',
        mtype: 'GET',
        colNames:['DID', 'UDID', 'Owner', 'Name', 'First seen', 'Last seen'],
        colModel :[ 
          {name:'did', index:'did', width: 30, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'udid', index:'udid', width: 120, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_owner', index:'d_owner', width: 70, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_name', index:'d_name', editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_firstseen', index:'d_firstseen', width: 80}, 
          {name:'d_lastseen', index:'d_lastseen', width: 80}],
        pager: jQuery('#pager'),
        rowNum:20,
        rowList:[20,50,100],
        sortname: 'did',
        sortorder: "desc",
        multiselect: true,
        viewrecords: true,
        imgpath: 'themes/basic/images',
        caption: 'Devices list',
        height: 330,
        width: 1000,
        onSelectRow: function(id) {
            var id = $("#list").getRowData(id).message_id;
            message_id = id;
        },
        editurl: "{% url views.manage.deviceseditajax %}"
    });

当我在JqGrid中编辑行时,我收到了来自editurl的错误信息:

禁止访问 (403) CSRF验证失败。请求被中止。

这是因为csrf_token没有和其他数据一起传递到editurl。
我该如何将csrf_token添加到发送给editurl的POST请求中呢?

这段代码运行得很好(这是完整的jqgrid初始化代码):

     jQuery("#list").jqGrid({
        url:'{% url views.manage.devicesajax %}',
        datatype: 'json',
        mtype: 'GET',
        colNames:['DID', 'UDID', 'Owner', 'Name', 'First seen', 'Last seen'],
        colModel :[ 
          {name:'did', index:'did', width: 30, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'udid', index:'udid', width: 120, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_owner', index:'d_owner', width: 70, editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_name', index:'d_name', editable: true, searchoptions:{sopt:['eq','ne','bw','cn']}}, 
          {name:'d_firstseen', index:'d_firstseen', width: 80}, 
          {name:'d_lastseen', index:'d_lastseen', width: 80}],
        pager: jQuery('#pager'),
        rowNum:20,
        rowList:[20,50,100],
        sortname: 'did',
        sortorder: "desc",
        multiselect: true,
        viewrecords: true,
        imgpath: 'themes/basic/images',
        caption: 'Devices list',
        height: 330,
        width: 1000,
        editurl: "{% url views.manage.deviceseditajax %}",
    });

      jQuery("#list").navGrid('#pager',{edit:true,add:true,del:true,search:true},
        {
            closeAfterEdit:true,
            reloadAfterSubmit:true,
            closeOnEscape:true,
            editData: {csrfmiddlewaretoken: '{{ csrf_token }}'}
        },
        {
            closeAfterAdd:true,
            reloadAfterSubmit:true,
            closeOnEscape:true,
            editData: {csrfmiddlewaretoken: '{{ csrf_token }}'}
        }, 
        {
            closeOnEscape:true,
            delData: {csrfmiddlewaretoken: '{{ csrf_token }}'}
        }, 
        {
         caption: "Search",
         Find: "Find",
         Reset: "Reset",
         sopt  : ['eq', 'cn'],
         matchText: " match",
         rulesText: " rules",
         closeAfterSearch: true,
         afterShowSearch: function ()
         {
             $('#reset_filter1_block').show();
         }
       }
      );

4 个回答

0

检查一下你的 cookies。Django 的 CSRF 保护也会保存一个叫 csrftoken 的 cookie,它的值和你在表单中使用的 csrf_token 是一样的。你可以用任何一个 JavaScript 的 cookie 库来获取这个 cookie,然后把它作为 csrfmiddlewaretoken 传给 POST 请求。

0

根据 jqGrid 的文档,你可以传递一个 postData 选项。

如果你在使用 jQuery Cookie 插件,你可以在你的 jqGrid 选项中添加类似下面的内容:

postData: {
    csrfmiddlewaretoken: $.cookie(CSRF_COOKIE_NAME)
},

这样就可以把它加到 jqGrid 的选项列表里了。

CSRF_COOKIE_NAME 是在你的 Django 应用的 settings.py 文件中设置的,默认值是 'csrftoken'。

3

我不太使用Django框架,也不太了解csrf_token,不过我在谷歌上查了一下,发现你需要把它放在请求的HTTP头里:xhr.setRequestHeader('X-CSRF-Token', csrf_token);。如果你在使用jqGrid,可以通过loadBeforeSend事件处理器来做到这一点:

loadBeforeSend: function(jqXHR) {
    // you should modify the next line to get the CSRF tocken
    // in any way (for example $('meta[name=csrf]').attr('content')
    // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
    var csrf_token = '<%= token_value %>'; // any way to get
    jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
}

你可以在这里查看一个非常相似的问题。

更新:如果你在编辑表单时需要发送额外的数据,可以使用editData:editData: { csrfmiddlewaretoken:'<%= token_value %>' }。例如:

jQuery("#list").jqGrid('navGrid','#pager',{},
    { // Edit option (parameters of editGridRow method)
        recreateForm:true,
        reloadAfterSubmit:false,
        closeOnEscape:true,
        savekey: [true,13],
        closeAfterEdit:true,
        ajaxEditOptions: {
            beforeSend: function(jqXHR) {
                // you should modify the next line to get the CSRF tocken
                // in any way (for example $('meta[name=csrf]').attr('content')
                // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
                var csrf_token = '<%= token_value %>'; // any way to get
                jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
            }
        },
        editData: {
            csrfmiddlewaretoken: '<%= token_value %>'
        }
    },
    { // Add options (parameters of editGridRow method)
        recreateForm:true,
        reloadAfterSubmit:false,
        closeOnEscape:true,
        savekey: [true,13],
        closeAfterAdd:true,
        ajaxEditOptions: {
            beforeSend: function(jqXHR) {
                // you should modify the next line to get the CSRF tocken
                // in any way (for example $('meta[name=csrf]').attr('content')
                // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
                var csrf_token = '<%= token_value %>'; // any way to get
                jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
            }
        },
        editData: {
            csrfmiddlewaretoken: '<%= token_value %>'
        }
    }
);

我这里提供了两种方法:一种是设置'X-CSRF-Token'的HTTP头,另一种是发送csrfmiddlewaretoken参数。你可以在相应的实验后删除其中一种方法。

如果你在页面上对所有的网格使用一些参数,最好是修改默认设置(详细信息请见这里)。

jQuery.extend(jQuery.jgrid.edit, {
    recreateForm:true,
    reloadAfterSubmit:false,
    closeOnEscape:true,
    savekey: [true,13],
    closeAfterAdd:true,
    closeAfterEdit:true,
    ajaxEditOptions: {
        beforeSend: function(jqXHR) {
            // you should modify the next line to get the CSRF tocken
            // in any way (for example $('meta[name=csrf]').attr('content')
            // if you have <meta name="csrf" content="abcdefjklmnopqrstuvwxyz="/>)
            var csrf_token = '<%= token_value %>'; // any way to get
            jqXHR.setRequestHeader('X-CSRF-Token', csrf_token);
        }
    },
    editData: {
        csrfmiddlewaretoken: '<%= token_value %>'
    }
});

这个设置对添加和编辑表单都是通用的。所以你可以在简化的形式中使用navGrid

jQuery("#list").jqGrid('navGrid','#pager');

撰写回答