【问题标题】:How to pass csrf_token to the post params of editurl of jqgrid?如何将 csrf_token 传递给 jqgrid 的 editurl 的 post 参数?
【发布时间】:2011-09-22 11:55:18
【问题描述】:

我将 JqGrid 与 Django 框架一起使用。那是JS:

      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 init 片段):

     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();
         }
       }
      );

【问题讨论】:

    标签: javascript python django jqgrid


    【解决方案1】:

    我找到了简单的解决方案,使用最新的 JqGrid 和内联编辑提交 csrf_token 来请求没有 @csrf_exempt 的 POST django

    onSelectRow: function(id){
         if(id && id!==lastSel){ 
            $(selector).restoreRow(lastSel); 
            lastSel=id; 
         }
    
         var editparameters = {
            extraparam: {csrfmiddlewaretoken: $('.token-data').data('token')},
            keys: true,
          };
         $(selector).jqGrid('editRow', id, editparameters);
    
    }
    

    例如,请参阅我的博文: http://yodi.polatic.me/jqgrid-inline-editing-integration-with-django-send-csrf-token/

    【讨论】:

      【解决方案2】:

      我没有使用django框架,对csrf_token不熟悉,但是在google上搜索后似乎需要在请求的http header中设置: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);
      }
      

      请参阅here 了解非常接近的问题。

      更新:要在表单编辑使用情况下发布其他数据,您可以使用editData:editData: { csrfmiddlewaretoken:'' }。例如:

      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 参数。您可以在相应的实验后删除一种方式。

      如果您为页面上的所有网格使用某些参数,您可以更好地更改默认值(详情请参阅here

      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');
      

      【讨论】:

      • @futureboxlab :刚才我重读了您的问题,发现您的问题不是填充网格内容,而是网格编辑。因此,您应该使用jQuery.ajaxbeforeSend 处理程序,它的作用与我在回答中描述的相同。要设置内联编辑的事件处理程序,您可以使用ajaxRowOptions 选项或ajaxEditOptions 选项以防使用表单编辑。
      • 我试过了。但它在获取记录时发送此类标头,而不是在向 editurl 发出 POST 请求时发送。
      • @futureboxlab:我同意。我刚刚给你写了相应的评论。如果您需要,我可以更详细地解释。
      • @futureboxlab:首先我们要明确以下问题:您使用哪种编辑模式:inline editingform editing?下一个问题:你想在所有编辑请求中设置X-CSRF-Token HTTP 标头吗?
      • 我使用表单编辑。我需要它来处理所有请求。还有一件事:我不确定 headerparam 会起作用,但 post 变量肯定会起作用
      【解决方案3】:

      根据jqGrid documentation,可以传递一个postData选项。 如果你使用jQuery Cookie plugin,你可以添加类似:

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

      到您的 jqGrid 选项列表中。

      CSRF_COOKIE_NAME 在您的 django 应用程序 settings.py 中设置,默认为“csrftoken”。

      【讨论】:

      • 不幸的是,获取记录时发送了 postData。
      【解决方案4】:

      检查您的 cookie。 Django 的 CSRF 还保存了一个 cookie csrftoken,它的值与您将在表单中使用的 csrf_token 具有相同的值。您可以使用任何 Javascript cookie 库来获取 cookie 并将其作为 csrfmiddlewaretoken 传递给 POST 请求。

      【讨论】:

      • 我知道。获取 csrftoken 值很容易。但我不知道如何将它添加到帖子参数中。有任何 jqjrid 方法吗?
      猜你喜欢
      • 1970-01-01
      • 2014-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      相关资源
      最近更新 更多