Несоответствие токена csrf laravel для запроса POST ajax

114

Я пытаюсь удалить данные из базы данных через ajax.

HTML:

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

Мой код 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;
}
});

Это мой запрос на получение данных из базы данных ...

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

Но когда я нажимаю Удалить данные ссылки, не удаляются и показываю несоответствие csrf_token ...

Ашиш Сингх
источник
Проверьте это: stackoverflow.com/questions/53684928/…
Prateek
вы должны добавить успех и ошибку в свой код ajax. ошибка покажет проблему.stackoverflow.com/questions/45668337/…
reza jafari

Ответы:

177

Вы должны добавить данные в свой запрос ajax. Я надеюсь, что так будет работать.

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }
Дипак сайни
источник
32
Что делать, если функция ajax находится в .jsфайле?
Brane
1
Он не работает на Laravel 5.7. Зарпио ответ правильный.
Омар Мурсия
1
@Brane отправляет токен в качестве параметра функции
Абделалим Хассуна,
Это не работает в Laravel 5.8. Он по-прежнему говорит о несоответствии токенов. Посмотрите мой ответ ниже, чтобы найти простое решение
Gjaa
laravel меняет токен csrf после запроса json? вам нужно отправить новый на главную?
davefrassoni
187

Лучший способ решить эту проблему «X-CSRF-TOKEN» - это добавить следующий код в ваш основной макет и продолжить обычные вызовы ajax:

В заголовке

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

В сценарии

<script type="text/javascript">
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
</script>
зарпио
источник
5
Спасибо чувак. Это более продуманное решение! Таким образом, вы просто настраиваете его один раз, а затем просто пишете свой обычный код $ .ajax.
pkid169
4
Это лучшее решение, потому что вы можете использовать его внутри .jsфайлов
Адам
3
Лучший ответ на данный момент. Спасибо.
Павел Денисевич
что если "global: false"?
Мишель
1
Как можно обновлять csrf после каждого звонка? первый вызов работает отлично, последующие вызовы не работают из-за токена CSRF.
Jjsg08 01
28

Думаю, лучше поместить токен в форму, и получить этот токен по id

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

И JQUery:

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

таким образом, ваш JS не должен находиться в ваших файлах лезвия.

cmnardi
источник
25

Я только что добавил headers:в вызове ajax:

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

ввиду:

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

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

функция 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>

в контроллере:

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

в routes.php

Route::post('ajax', 'AjaxController@call');
lewis4u
источник
1
мне помогло добавление заголовков к вызову ajax.
Чаудри Вакас
1
Это лучший ответ, потому что он не требует наличия JavaScript в файле лезвия (если вы не хотите, чтобы он был в файле лезвия, но тогда он отображается каждый раз, когда кто-то заходит на эту страницу)
Захари Вейксельбаум,
12

Если вы используете файлы шаблонов, вы можете поместить свой metaтег в заголовок section(или как вы его называете), который содержит ваши metaтеги.

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

Далее вам нужно поместить headersатрибут в свой ajax(в моем примере я использую datatableобработку на стороне сервера:

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

Вот полный datatableпример 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);
           }
        }
    });

После этого вы должны получить 200 status по вашему ajaxзапросу.

Brane
источник
6

Знайте, что для удобства установлен файл cookie X-XSRF-TOKEN. Framework, как 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('....');

Вот рекомендуемый мета-способ (вы можете указать поле любым способом, но мета-вариант довольно приятный):

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

Обратите внимание на использование decodeURIComponent() , он декодируется из формата uri, который используется для хранения cookie. [иначе вы получите исключение недопустимой полезной нагрузки в laravel].

Здесь раздел о файле cookie csrf в документе для проверки: 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');
} 

можешь пойти проверить 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;
    }
Мохамед Аллал
источник
5

Добавьте idк metaэлементу, содержащему токен

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

И тогда вы можете получить его в своем Javascript

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

РЕДАКТИРОВАТЬ: более простой способ без изменения metaстроки.

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

Или

data : { 
    _token: @json(csrf_token()), 
}

Спасибо @ martin-hartmann

Gjaa
источник
2
Если вы не хотите добавлять идентификатор, просто используйте вместо него: $ ("[name = csrf-token]"). Attr ("content"). Он выберет правильный элемент по атрибуту name.
Педро Соуза
1
Также можно просто указать объявление в поле данных: data: {"_token": "{{csrf_token ()}}" // передать CSRF_TOKEN ()},
Мартин Хартманн,
3

если вы используете 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;
}

Laravel добавляет файл cookie XSRF ко всем запросам, и мы автоматически добавляем его ко всем запросам AJAX непосредственно перед отправкой.

Вы можете заменить функцию getCookie, если есть другая функция или плагин jQuery, делающие то же самое.

AMIB
источник
1

Для Laravel 5.8 установка метатега csrf для вашего макета и установка заголовка запроса для csrf в настройках ajax не будут работать, если вы используете ajax для отправки формы, которая уже включает _tokenполе ввода, сгенерированное механизмом создания шаблонов Laravel blade.

Вы должны включить уже сгенерированный токен csrf из формы с вашим запросом ajax, потому что сервер будет ожидать его, а не тот, который указан в вашем метатеге.

Например, так выглядит _tokenполе ввода, созданное Blade:

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

Затем вы отправляете свою форму с помощью ajax следующим образом:

<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>

Токен csrf в мета-заголовке полезен только тогда, когда вы отправляете форму без _tokenполя ввода, созданного Blade .

Удо Э.
источник
1

у кого-либо возникают проблемы с принятым ответом @Deepak saini, попробуйте удалить

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

для вызова ajax.

использовать

dataType:"json",
Мрудул Аддипалли
источник
0

У меня действительно была эта ошибка, и я не мог найти решение. На самом деле я закончил тем, что не выполнял запрос ajax. Я не знаю, была ли эта проблема связана с тем, что это поддомен на моем сервере или что-то еще. Вот мой 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" );
                        }
                      }
                    });
                  });
                });

Поэтому я фактически установил привязку для перехода к моему API, а не для выполнения почтового запроса, что, как я полагаю, делает большинство приложений.

  <p><a href="http://<?php echo $domain; ?>/mealtrist/meals/delete/{{ $meal->id }}" id="deleteMealLink" data-mealId="{{$meal->id}}" ></a></p>
Dlaugh14
источник
0

Вы должны включить скрытое поле токена CSRF (подделка межсайтовых запросов) в форму, чтобы защита CSRF промежуточное ПО могло проверить запрос.

Laravel автоматически генерирует «токен» CSRF для каждой активной пользовательской сессии, управляемой приложением. Этот токен используется для проверки того, что аутентифицированный пользователь действительно отправляет запросы к приложению.

Поэтому при выполнении запросов ajax вам необходимо передать токен csrf через параметр данных. Вот пример кода.

var request = $.ajax({
    url : "http://localhost/some/action",
    method:"post",
    data : {"_token":"{{ csrf_token() }}"}  //pass the CSRF_TOKEN()
  });
Нава Богати
источник
0

Я просто использую @csrf внутри формы, и он отлично работает

себя
источник