Ajax POST 요청에 대한 Laravel csrf 토큰 불일치


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

내 아약스 코드 :

$('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 불일치가 표시됩니다 ...



ajax 코드에 성공과 오류를 추가해야합니다. 오류가 문제를 보여줍니다. stackoverflow.com/questions/45668337/...
레자 jafari

답변:


177

ajax 요청에 데이터 를 추가해야합니다 . 그렇게 될 수 있기를 바랍니다.

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

32
ajax 함수가 .js파일 에 있으면 어떻게됩니까?
Brane

1
Laravel 5.7에서는 작동하지 않습니다. zarpio의 대답이 맞습니다.
Omar Murcia

1
기능의 PARAM로 토큰을 보내 @Brane
Abdelalim Hassouna에게

Laravel 5.8에서는 작동하지 않습니다. 여전히 토큰 불일치라고 말합니다. 간단한 해결책에 대한 내 대답을 아래에서 확인하십시오
Gjaa

laravel은 json 요청 후 csrf 토큰을 변경합니까? 새로운 것을 메인 페이지로 보내야합니까?
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파일 내에서 사용할 수 있기 때문에 더 나은 솔루션입니다
Adam

3
지금까지 최고의 답변입니다. 감사.
Paul Denisevich

"global : false"이면 어떨까요?
Michel

1
각 호출 후 csrf를 어떻게 업데이트 할 수 있습니까? 첫 번째 호출은 훌륭하게 작동하고 CSRF 토큰으로 인해 하위 보안 호출이 실패합니다.
Jjsg08

28

토큰을 형식에 넣고이 토큰을 ID로 얻는 것이 더 낫다고 생각합니다.

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

그리고 JQUery :

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

이렇게하면 JS가 블레이드 파일에있을 필요가 없습니다.


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

아약스 기능 :

<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', 'AjaxController@call');

1
ajax 호출에 헤더를 추가하면 도움이되었습니다.
Chaudhry Waqas 2017

1
블레이드 파일에 JavaScript가 필요하지 않기 때문에 이것이 최선의 대답입니다 (블레이드 파일에 포함되기를 원하지만 누군가가 해당 페이지에 올 때마다 렌더링되는 경우 제외)
Zachary Weixelbaum

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

다음은 전체 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);
           }
        }
    });

이렇게하면 요청 을 받아야 200 status합니다 ajax.


6

편의를 위해 설정된 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('....');

여기에 권장되는 메타 방식이 있습니다 (어떤 방식 으로든 필드를 넣을 수 있지만 메타는 조용합니다) :

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

의 사용을 참고 decodeURIComponent()쿠키를 저장하는 데 사용되는 URI 형식에서 그것의 디코딩. [그렇지 않으면 laravel에서 잘못된 페이로드 예외가 발생합니다].

다음은 확인할 문서의 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.

그리고 여기 쿠키 기능을 읽으십시오.

   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 덕분에


2
ID를 추가하지 않으려면 대신 $ ( "[name = csrf-token]"). attr ( "content")를 사용하십시오. 이름 속성으로 올바른 요소를 가져옵니다.
Pedro Sousa

1
데이터 필드에만 광고 할 수도 있습니다. data : { "_token": "{{csrf_token ()}}"// CSRF_TOKEN () 통과},
Martin Hartmann

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은 모든 요청에 ​​XSRF 쿠키를 추가하고 제출 직전에 모든 AJAX 요청에 자동으로 추가합니다.

동일한 작업을 수행하는 다른 함수 또는 jQuery 플러그인이있는 경우 getCookie 함수를 대체 할 수 있습니다.


1

Laravel 5.8의 경우 레이아웃에 대한 csrf 메타 태그를 설정하고 ajax 설정에서 csrf에 대한 요청 헤더를 설정하는 것은 ajax를 사용하여 이미 포함 된 양식을 제출하는 경우 작동하지 않습니다. _token Laravel 블레이드 템플릿 엔진에서 생성 한 입력 필드 .

ajax 요청과 함께 양식에서 이미 생성 된 csrf 토큰을 포함해야합니다. 서버가 메타 태그에있는 것이 아니라이를 예상하기 때문입니다.

예를 들어, _tokenBlade가 생성 한 입력 필드는 다음과 같습니다.

<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 토큰은 Blade 생성 _token입력 필드 없이 양식을 제출할 때만 유용 합니다.


1

받아 들인 대답 @Deepak saini에 문제가있는 사람은 제거하십시오.

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

아약스 호출.

사용하다

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>

0

CSRF 보호 미들웨어가 요청을 검증 할 수 있도록 양식에 숨겨진 CSRF (사이트 간 요청 위조) 토큰 필드를 포함해야합니다 .

라 라벨은 애플리케이션이 관리하는 각 활성 사용자 세션에 대해 CSRF "토큰"을 자동으로 생성합니다. 이 토큰은 인증 된 사용자가 실제로 애플리케이션에 대한 요청을 수행하는 사람인지 확인하는 데 사용됩니다.

따라서 ajax 요청을 수행 할 때 데이터 매개 변수를 통해 csrf 토큰 을 전달해야합니다 . 다음은 샘플 코드입니다.

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

0

나는 양식 내부에서 @csrf를 사용하고 잘 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.