Laravel csrf令牌与ajax POST请求不匹配

Ash*_*ngh 68 php ajax jquery laravel

我试图通过ajax从数据库中删除数据.

HTML:

@foreach($a as $lis)
  //some code
  <a href="#" class="delteadd" id="{{$lis['id']}}">Delete</a>
  //click action perform on this link                  
@endforeach
Run Code Online (Sandbox Code Playgroud)

我的ajax代码:

$('body').on('click', '.delteadd', function (e) {
e.preventDefault();
//alert('am i here');
if (confirm('Are you sure you want to Delete Ad ?')) {
    var id = $(this).attr('id');
    $.ajax({
        method: "POST",
        url: "{{url()}}/delteadd",
        }).done(function( msg ) {
        if(msg.error == 0){
            //$('.sucess-status-update').html(msg.message);
            alert(msg.message);
        }else{
            alert(msg.message);
            //$('.error-favourite-message').html(msg.message);
        }
    });
} else {
    return false;
}
});
Run Code Online (Sandbox Code Playgroud)

这是我从数据库中获取数据的查询...

$a = Test::with('hitsCount')->where('userid', $id)->get()->toArray();
Run Code Online (Sandbox Code Playgroud)

但当我点击删除链接数据未删除并显示csrf_token不匹配...

zar*_*pio 128

解决此问题的最佳方法"X-CSRF-TOKEN"是将以下代码添加到主布局中,并继续正常进行ajax调用:

在标题中

<meta name="csrf-token" content="{{ csrf_token() }}" />
Run Code Online (Sandbox Code Playgroud)

在脚本中

<script type="text/javascript">
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
</script>
Run Code Online (Sandbox Code Playgroud)

  • 谢啦.这是一个更全面的解决方案!这样你就可以设置一次,之后只需编写正常的$ .ajax代码. (5认同)
  • 这是更好的解决方案,因为您可以在`.js`文件中使用它 (4认同)
  • 到目前为止最佳答案.谢谢. (3认同)
  • 每次调用后如何更新 csrf?第一次调用效果很好,由于 CSRF 令牌,后续调用失败。 (3认同)

Dee*_*ini 124

您必须在ajax请求中添加数据.我希望它能起作用.

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }
Run Code Online (Sandbox Code Playgroud)

  • 如果ajax函数位于`.js`文件中怎么办? (23认同)
  • @Brane 将令牌作为函数中的参数发送 (3认同)
  • 它不适用于 Laravel 5.7。zarpio 的回答是正确的。 (2认同)

cmn*_*rdi 25

我认为最好将令牌放在表单中,并通过id获取此令牌

<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}">
Run Code Online (Sandbox Code Playgroud)

和JQUery:

var data = {
        "_token": $('#token').val()
    };
Run Code Online (Sandbox Code Playgroud)

这样,您的JS不需要在您的刀片文件中.


lew*_*s4u 15

我刚刚headers:在ajax调用中添加:

  headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
Run Code Online (Sandbox Code Playgroud)

在视图中:

<div id = 'msg'>
     This message will be replaced using Ajax. Click the button to replace the message.
</div>

{{ Form::submit('Change', array('id' => 'ajax')) }}
Run Code Online (Sandbox Code Playgroud)

ajax功能:

<script>
 $(document).ready(function() {
    $(document).on('click', '#ajax', function () {
      $.ajax({
         type:'POST',
         url:'/ajax',
         headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
         success:function(data){
            $("#msg").html(data.msg);
         }
      });
    });
});
</script>
Run Code Online (Sandbox Code Playgroud)

在控制器中:

public function call(){
    $msg = "This is a simple message.";
    return response()->json(array('msg'=> $msg), 200);
}
Run Code Online (Sandbox Code Playgroud)

在routes.php中

Route::post('ajax', 'AjaxController@call');
Run Code Online (Sandbox Code Playgroud)


Bra*_*ane 10

如果您使用的是模板文件,那么您可以将meta标记放在包含标记的头部section(或任何您的名称)中meta.

@section('head')
<meta name="csrf_token" content="{{ csrf_token() }}" />
@endsection
Run Code Online (Sandbox Code Playgroud)

接下来,你需要把headers属性放到你的ajax(在我的例子中,我使用datatable服务器端处理:

"headers": {'X-CSRF-TOKEN': $('meta[name="csrf_token"]').attr('content')}
Run Code Online (Sandbox Code Playgroud)

这是完整的datatableajax示例:

$('#datatable_users').DataTable({
        "responsive": true,
        "serverSide": true,
        "processing": true,
        "paging": true,
        "searching": { "regex": true },
        "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ],
        "pageLength": 10,
        "ajax": {
            "type": "POST",
            "headers": {'X-CSRF-TOKEN': $('meta[name="csrf_token"]').attr('content')},
            "url": "/getUsers",
            "dataType": "json",
            "contentType": 'application/json; charset=utf-8',
            "data": function (data) {
                console.log(data);
            },
            "complete": function(response) {
                console.log(response);
           }
        }
    });
Run Code Online (Sandbox Code Playgroud)

这样做之后,你应该得到200 status你的ajax要求.


Moh*_*lal 9

知道有一个 X-XSRF-TOKEN cookie 是为了方便而设置的。Angular 等框架默认设置它。在文档https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token 中检查 您可能喜欢使用它。

最好的方法是使用元,以防 cookie 被停用。

    var xsrfToken = decodeURIComponent(readCookie('XSRF-TOKEN'));
    if (xsrfToken) {
        $.ajaxSetup({
            headers: {
                'X-XSRF-TOKEN': xsrfToken
            }
        });
    } else console.error('....');
Run Code Online (Sandbox Code Playgroud)

这里推荐的元方式(你可以以任何方式放置该字段,但元很安静):

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});   
Run Code Online (Sandbox Code Playgroud)

注意 的使用decodeURIComponent(),它是从用于存储 cookie 的 uri 格式解码的。[否则你会在 laravel 中得到一个无效的负载异常]。

这里有关文档中的 csrf cookie 的部分要检查:https ://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

同样在这里,laravel (bootstrap.js) 默认情况下如何为 axios 设置它:

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
} 
Run Code Online (Sandbox Code Playgroud)

你可以去检查resources/js/bootstrap.js

在这里读取 cookie 功能:

   function readCookie(name) {
        var nameEQ = name + "=";
        var ca = document.cookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') c = c.substring(1, c.length);
            if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
       }
        return null;
    }
Run Code Online (Sandbox Code Playgroud)


小智 9

你必须在主文件中包含这一行

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

在调用 ajax 时,您必须实现 csrf token ,

$.ajax({
url:url,
data:{
 _token:"{{ csrf_token() }}"
},
success:function(result){
 //success message after the controller is done..
}
})
Run Code Online (Sandbox Code Playgroud)


Gja*_*jaa 7

idmeta包含令牌的元素添加一个

<meta name="csrf-token" id="csrf-token" content="{{ csrf_token() }}">
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的 Javascript 中得到它

$.ajax({
  url : "your_url",
  method:"post",
  data : {
    "_token": $('#csrf-token')[0].content  //pass the CSRF_TOKEN()
  },  
  ...
});
Run Code Online (Sandbox Code Playgroud)

编辑:更简单的方法而不改变meta线路。

data : { 
    _token: "{{ csrf_token() }}" 
}
Run Code Online (Sandbox Code Playgroud)

或者

data : { 
    _token: @json(csrf_token()), 
}
Run Code Online (Sandbox Code Playgroud)

感谢@martin-hartmann

  • 如果您不想添加 id,只需使用: $("[name=csrf-token]").attr("content") 即可。它将通过 name 属性获取正确的元素。 (2认同)

AMI*_*MIB 5

如果您使用 jQuery 发送 AJAX 帖子,请将此代码添加到所有视图:

$( document ).on( 'ajaxSend', addLaravelCSRF );

function addLaravelCSRF( event, jqxhr, settings ) {
    jqxhr.setRequestHeader( 'X-XSRF-TOKEN', getCookie( 'XSRF-TOKEN' ) );
}

function getCookie(name) {
    function escape(s) { return s.replace(/([.*+?\^${}()|\[\]\/\\])/g, '\\$1'); };
    var match = document.cookie.match(RegExp('(?:^|;\\s*)' + escape(name) + '=([^;]*)'));
    return match ? match[1] : null;
}
Run Code Online (Sandbox Code Playgroud)

Laravel 向所有请求添加 XSRF cookie,并且我们会在提交之前自动将其附加到所有 AJAX 请求。

如果有其他函数或 jQuery 插件可以执行相同的操作,您可以替换 getCookie 函数。