【问题标题】:Renew CSRF after form submit提交表单后更新 CSRF
【发布时间】:2020-07-23 19:22:06
【问题描述】:

我想实现我在该图像中显示的功能。用户将单击编辑按钮并激活页面中单个字段的表单。

使用 Ajax 我将更新模型并在成功后再次恢复显示。这里的问题是 CSRF_TOKEN。用户更新第一个字段后,无论是哪个字段,第二次编辑都会返回错误 500 token mismatch 消息。

我尝试了许多不同的方法,包括我在这里看到的最后一种方法:

$.ajaxSetup( {
  beforeSend: function( xhr, settings ){
    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;
    }
    if( !( /^http:.*/.test( settings.url ) || /^https:.*/.test( settings.url ) ) ){
      // Only send the token to relative URLs i.e. locally.
      xhr.setRequestHeader( "X-CSRFToken", getCookie( 'csrftoken' ) );
    }
  }
} );

但我仍然在第二次提交时收到错误。我知道我需要做的就是在我的元 &lt;meta name="csrf-token" content="{{ csrf_token() }}"&gt; 中更新令牌的值,但我没有关于如何做到这一点的想法,我真的想在不刷新页面的情况下保留此功能。

也许从返回结果的控制器发送新的 CSRF 并在我的成功阶段在 ajax 请求中使用$( 'meta[name="csrf-token"]' ).val( response.csrf ); 之类的东西?

【问题讨论】:

  • 出于某种原因,我可以毫无问题地提交任意数量的请求。

标签: jquery laravel ajaxform csrf-token


【解决方案1】:
       $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
            }
        });

【讨论】:

  • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常质量更高,更有可能吸引投票。
  • 我已经在其他不同的帖子中看到了这个答案,但没有成功。抱歉,但这不是我的问题的正确答案。
【解决方案2】:

我的回答包括修改至少两个文件,即执行 ajax 的模板和接收表单请求的控制器。所有从页面中的表单接收动作的方法都应该返回更新后的 csrf 令牌,并且所有包含 csrf 值的字段(如果有)也应该在 ajax 执行后更新。

首先,刀片模板将为文档中的所有表单使用通用 csrf 令牌,为此,我像往常一样将元 csrf-token 添加到我的标题部分:

<meta name="csrf-token" content="{{ csrf_token() }}">

现在,ajax 脚本必须在表单中插入令牌并在执行模板中的任何表单后更新元:

$( 'body' ).on( 'submit', '.form', function( event ){
  event.preventDefault();
  let fd = new FormData( $( this )[ 0 ] );
  fd.append( '_token', $( 'meta[name="csrf-token"]' ).attr( 'content' ) )

  $.ajax( {
    url : '{{ route( 'service.update', [ 'service' => $service ] ) }}',
    method : 'post',
    data : fd,
    contentType: false,
    processData: false,
    success: function( response ){
      $( 'meta[name="csrf-token"]' ).attr( 'content', response.token );
      //Do all the other things that need to be done...
    },
    error: function( xhr, status, error ){
      console.log( error );
    }
  } );
} );

现在,我要做的第一件事是使用表单的内容创建一个 FormData 对象,并将元数据中的 csrf 值添加到字段集 (fd.append( '_token', $( 'meta[name="csrf-token"]' ).attr( 'content' ) ))。

执行完成后,我的 javascript 将收到一个带有 .token 值的响应变量,其中包含新的 csrf-token 值,因此我将旧的元值更新为新的值:$( 'meta[name="csrf-token"]' ).attr( 'content', response.token );

现在,对于控制器端,我需要做的就是将令牌值添加到 jSon 中,在我的情况下它是一个数组,所以我只需要像这样添加它:

$response[ 'token' ] = $request->session()->token();
return $response;

现在表格可以正常工作了,谢谢

【讨论】:

    猜你喜欢
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多