Laravel csrf token mismatch para ajax POST Request


113

Estou tentando excluir dados do banco de dados via ajax.

HTML:

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

Meu código 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;
}
});

Esta é minha consulta para buscar dados do banco de dados ...

$a = Test::with('hitsCount')->where('userid', $id)->get()->toArray();

Mas quando clico em Excluir dados de link não excluídos e mostro incompatibilidade csrf_token ...



você deve adicionar sucesso e erro ao seu código Ajax. o erro mostrará o problema. stackoverflow.com/questions/45668337/…
— reza jafari

Respostas:


176

Você deve adicionar dados em sua solicitação ajax. Espero que dê certo.

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }

32
E se a função ajax estiver localizada no .jsarquivo?
— Brane

1
Não funciona no Laravel 5.7. A resposta de zarpio está correta.
— Omar Murcia

1
@Brane envia o token como um parâmetro na função
— Abdelalim Hassouna

Isso não funciona no Laravel 5.8. Ele ainda indica incompatibilidade de token. Verifique minha resposta abaixo para uma solução simples
— Gjaa

o laravel altera o token csrf após uma solicitação json? você precisa enviar o novo para a página principal?
— davefrassoni

184

A melhor maneira de resolver este problema "X-CSRF-TOKEN" é adicionar o seguinte código ao seu layout principal e continuar fazendo suas chamadas ajax normalmente:

No cabeçalho

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

No script

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

5
Obrigado cara. Esta é uma solução mais completa! Dessa forma, você apenas configura uma vez e, a partir daí, começa a escrever seu código $ .ajax normal.
— pkid169

4
Esta é a melhor solução porque você pode usá-la dentro de .jsarquivos
— Adam

3
Melhor resposta até agora. Obrigado.
— Paul Denisevich

e se "global: false"?
— Michel

1
Como o csrf pode ser atualizado após cada chamada? a primeira chamada funciona bem, as chamadas subsequentes falham devido ao token CSRF.
— Jjsg08 01 de

28

Acho melhor colocar o token no formulário, e pegar esse token por id

<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}">

E o JQUery:

var data = {
        "_token": $('#token').val()
    };

dessa forma, seu JS não precisa estar em seus arquivos blade.


25

Acabei de adicionar headers:na chamada ajax:

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

em vista:

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

{{ Form::submit('Change', array('id' => 'ajax')) }}

função 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>

no controlador:

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

em routes.php

Route::post('ajax', 'AjaxController@call');

1
adicionar cabeçalhos à chamada ajax me ajudou.
— Chaudhry Waqas,

1
Esta é a melhor resposta porque não requer que o JavaScript esteja em um arquivo blade (a menos que você queira em um arquivo blade, mas ele está sendo renderizado toda vez que alguém
— acessa

11

Se você estiver usando arquivos de modelo, então você pode colocar sua metatag no cabeçalho section(ou qualquer que seja o nome) que contém suas metatags.

@section('head')
<meta name="csrf_token" content="{{ csrf_token() }}" />
@endsection

Em seguida, você precisa colocar o headersatributo em seu ajax(no meu exemplo, estou usando datatablecom processamento do lado do servidor:

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

Aqui está o datatableexemplo completo de Ajax:

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

Depois de fazer isso, você deverá atender 200 statusao seu ajaxpedido.


6

Saiba que existe um cookie X-XSRF-TOKEN configurado para sua conveniência. Framework como Angular e outros o definem por padrão. Verifique isso no documento https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token. Você pode gostar de usá-lo.

A melhor forma é usar o meta, caso os cookies estejam desativados.

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

Aqui está o método meta recomendado (você pode colocar o campo de qualquer maneira, mas o meta é muito bom):

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

Observe o uso de decodeURIComponent(), é decodificado do formato uri que é usado para armazenar o cookie. [caso contrário, você obterá uma exceção de carga útil inválida no laravel].

Aqui está a seção sobre o cookie csrf no documento para verificar: https://laravel.com/docs/5.7/csrf#csrf-x-csrf-token

Também aqui como laravel (bootstrap.js) está configurando para axios por padrão:

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

você pode ir verificar resources/js/bootstrap.js.

E aqui leia a função do 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;
    }

5

Adicione um idao metaelemento que contém o token

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

E então você pode obtê-lo em seu Javascript

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

1
Se você não quiser adicionar um id, basta usar: $ ("[name = csrf-token]"). Attr ("content") ao invés. Ele irá buscar o elemento certo pelo atributo name.
— Pedro Sousa

3

se você estiver usando jQuery para enviar Postagens AJAX, adicione este código a todas as visualizações:

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

O Laravel adiciona um cookie XSRF a todas as solicitações, e nós o anexamos automaticamente a todas as solicitações AJAX antes de enviar.

Você pode substituir a função getCookie se houver outra função ou plugin jQuery para fazer a mesma coisa.


1

Para o Laravel 5.8, definir a meta tag csrf para o seu layout e definir o cabeçalho da solicitação para csrf nas configurações do ajax não funcionará se você estiver usando o ajax para enviar um formulário que já inclui um _token campo de entrada gerado pelo motor de templates do Laravel.

Você deve incluir o token csrf já gerado do formulário com sua solicitação ajax porque o servidor estaria esperando por ele e não aquele em sua metatag.

Por exemplo, é assim que o _tokencampo de entrada gerado pelo Blade se parece:

<form>
    <input name="_token" type="hidden" value="cf54ty6y7yuuyyygytfggfd56667DfrSH8i">
    <input name="my_data" type="text" value="">
    <!-- other input fields -->
</form>

Em seguida, você envia seu formulário com ajax como este:

<script> 
    $(document).ready(function() { 
        let token = $('form').find('input[name="_token"]').val();
        let myData = $('form').find('input[name="my_data"]').val();
        $('form').submit(function() { 
            $.ajax({ 
                type:'POST', 
                url:'/ajax', 
                data: {_token: token, my_data: myData}
                // headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')}, // unnecessary 
                // other ajax settings
            }); 
            return false;
        }); 
    }); 
</script>

O token csrf no meta cabeçalho só é útil quando você está enviando um formulário sem um _tokencampo de entrada gerado pelo Blade .


1

quem está tendo problemas com a resposta aceita @Deepak saini, tente remover

cache:false,
processData:false,
contentType:false,

para chamada ajax.

usar

dataType:"json",

0

Na verdade, tive esse erro e não consegui encontrar uma solução. Na verdade, acabei não fazendo uma solicitação ajax. Não sei se este problema foi devido a ser um subdomínio no meu servidor ou o quê. Aqui está meu jquery.

            $('#deleteMeal').click(function(event) {
                var theId = $(event.currentTarget).attr("data-mealId");
                  $(function() {
                    $( "#filler" ).dialog({
                      resizable: false,
                      height:140,
                      modal: true,
                      buttons: {
                      "Are you sure you want to delete this Meal? Doing so will also delete this meal from other users Saved Meals.": function() {
                           $('#deleteMealLink').click();
//                         jQuery.ajax({
//                              url : 'http://www.mealog.com/mealtrist/meals/delete/' + theId,
//                              type : 'POST',
//                              success : function( response ) {
//                                  $("#container").replaceWith("<h1 style='color:red'>Your Meal Has Been Deleted</h1>");
//                              }
//                          });
                        // similar behavior as clicking on a link
                           window.location.href = 'http://www.mealog.com/mealtrist/meals/delete/' + theId;
                          $( this ).dialog( "close" );
                        },
                        Cancel: function() {
                          $( this ).dialog( "close" );
                        }
                      }
                    });
                  });
                });

Então, na verdade, configurei uma âncora para ir para minha API em vez de fazer uma solicitação de postagem, que é o que eu acho que a maioria dos aplicativos faz.

  <p><a href="http://<?php echo $domain; ?>/mealtrist/meals/delete/{{ $meal->id }}" id="deleteMealLink" data-mealId="{{$meal->id}}" ></a></p>

0

Você deve incluir um campo de token CSRF (falsificação de solicitação entre sites) oculto no formulário para que o middleware de proteção CSRF possa validar a solicitação.

O Laravel gera automaticamente um "token" CSRF para cada sessão de usuário ativa gerenciada pelo aplicativo. Esse token é usado para verificar se o usuário autenticado é quem realmente faz as solicitações ao aplicativo.

Portanto, ao fazer solicitações ajax, você precisará passar o token csrf por meio do parâmetro de dados. Aqui está o código de amostra.

var request = $.ajax({
    url : "http://localhost/some/action",
    method:"post",
    data : {"_token":"{{ csrf_token() }}"}  //pass the CSRF_TOKEN()
  });

0

Acabei de usar @csrf dentro do formulário e está funcionando bem

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.