it-swarm.com.ru

Laravel CSRF несоответствие токенов для AJAX POST Запрос

Я пытаюсь удалить данные из базы данных через 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 ...

52
Ashish Singh

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

data: {
        "_token": "{{ csrf_token() }}",
        "id": id
        }
94
Deepak saini

Лучший способ решить эту проблему «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>
89
zarpio

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

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

И JQUery: 

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

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

23
cmnardi

Я только что добавил 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);
}

в route.php

Route::post('ajax', '[email protected]');
11
lewis4u

Если вы используете файлы шаблонов, вы можете поместить свой тег 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.

9
raBne

если вы используете 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, который делает то же самое.

2
AMIB

Знайте, что существует файл cookie X-XSRF-TOKEN, который установлен для удобства. Фреймворк как Angular и другие устанавливают его по умолчанию. Проверьте это в документе https://laravel.com/docs/5.7/csrf#csrf-x-xsrf-token Вы можете использовать его.

Лучше всего использовать мету, если куки отключены.

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

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

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

Обратите внимание на использование decodeURIComponent(), это декодирование из формата uri, который используется для хранения куки. [иначе вы получите недопустимое исключение полезной нагрузки в 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;
    }
0
Mohamed Allal

Я действительно имел эту ошибку и не мог найти решение. Я фактически закончил тем, что не сделал запрос 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>
0
Dlaugh14

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

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

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

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