경고 : CSRF 토큰 진위 여부를 확인할 수 없습니다


238

AJAX를 사용하여보기에서 컨트롤러로 데이터를 보내고 있는데이 오류가 발생했습니다.

경고 : CSRF 토큰 진위를 확인할 수 없습니다

나는이 토큰을 데이터와 함께 보내야한다고 생각합니다.

아무도 내가 어떻게 할 수 있는지 알고 있습니까?

편집 : 내 솔루션

AJAX 포스트에 다음 코드를 넣어서이 작업을 수행했습니다.

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

7
당신은 않습니다 <csrf_meta_tag % = %> 레이아웃 헤더에?
Anatoly

yes like this : <% = csrf_meta_tags %>
kbaccouche

6
당신은 할 JQuery와 - 레일 아약스 클라이언트 측 기능을 제공하는 라이브러리를?
Anatoly

2
그리고 HAML 방법은 "= csrf_meta_tags"를 추가하는 것입니다
Ege Akpinar

좋은 질문, 물어 주셔서 감사합니다
AMIC MING

답변:


374

이 작업을 수행해야합니다.

  1. <%= csrf_meta_tag %>레이아웃에 있는지 확인하십시오

  2. 추가 beforeSend모든 아래와 같이 헤더를 설정하는 아약스 요청을 :


$.ajax({ url: 'YOUR URL HERE',
  type: 'POST',
  beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
  data: 'someData=' + someData,
  success: function(response) {
    $('#someDiv').html(response);
  }
});

모든 요청에서 토큰을 보내려면 다음을 사용할 수 있습니다.

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

5
감사! 나를 위해 매력처럼 일했다!
Misha Moroshko

35
Rails 팀이 제공 한 jQuery UJS 라이브러리는 CSRF 토큰을 jQuery AJAX 요청에 자동으로 추가합니다. 읽어보기에는 설정 방법에 대한 지침이 포함되어 있습니다. github.com/rails/jquery-ujs/blob/master/src/rails.js#L91
James Conroy-Finn

1
$ .ajaxSetup 함수를 사용하여 모든 요청에 ​​대한 헤더를 한 번에 설정할 수 있습니다.
피터 종 스마

1
우수한! 이 답변에 대해 잠시 동안 검색했습니다. 원활하게 작동합니다. 감사!
cassi.lup

4
참고로 위에서 제안한대로 jQuery UJS를 사용하는 경우 rails-ujs include가 jquery include 이후 에 오거나 op와 동일한 오류로 실패 하는지 확인해야합니다 .
Topher Fangio

31

이를 수행하는 가장 좋은 방법은 실제로 <%= form_authenticity_token.to_s %>레일 코드에서 직접 토큰을 인쇄하는 데 사용 하는 것입니다. 다른 게시물에서 언급했듯이 자바 스크립트를 사용하여 csrf 토큰의 돔을 검색 할 필요는 없습니다. 아래와 같이 헤더 옵션을 추가하십시오.

$.ajax({
  type: 'post',
  data: $(this).sortable('serialize'),
  headers: {
    'X-CSRF-Token': '<%= form_authenticity_token.to_s %>'
  },
  complete: function(request){},
  url: "<%= sort_widget_images_path(@widget) %>"
})

7
각 ajax 명령에 대해이 작업을 수행하는 대신 $ .ajaxSetup ()에 헤더 를 추가 할 수 있습니다 .
Scott McMillin


14
나는 자바 스크립트에서 ERB를 사용하는 접근법을 정말로 좋아하지 않습니다.
radixhound

이것은 ERB를 사용하여 자바 스크립트를 생성하도록 강제합니다. ERB가 적합 할 수있는 장소가 있더라도 그렇지 않은 곳이 있으며 토큰을 얻기 위해 추가하는 것은 낭비입니다.
sockmonk

22

올바르게 기억한다면이 문제를 해결하기 위해 양식에 다음 코드를 추가해야합니다.

<%= token_tag(nil) %>

매개 변수를 잊지 마십시오.


8
실제로 이것은 다음과 같아야합니다 <%= token_tag(nil) %>. 그런 다음 자동 생성 된 토큰을 얻습니다.
szeryf

15

실제로 가장 간단한 방법입니다. 헤더 변경에 신경 쓰지 마십시오.

당신이 가지고 있는지 확인하십시오 :

<%= csrf_meta_tag %> in your layouts/application.html.erb

다음과 같이 숨겨진 입력 필드를 수행하십시오.

<input name="authenticity_token" 
               type="hidden" 
               value="<%= form_authenticity_token %>"/>

또는 jQuery 아약스 게시물을 원한다면 :

$.ajax({     
    type: 'POST',
    url: "<%= someregistration_path %>",
    data: { "firstname": "text_data_1", "last_name": "text_data2", "authenticity_token": "<%= form_authenticity_token %>" },                                                                                  
    error: function( xhr ){ 
      alert("ERROR ON SUBMIT");
    },
    success: function( data ){ 
      //data response can contain what we want here...
      console.log("SUCCESS, data="+data);
    }
});

숨겨진 입력 필드를 입력 양식에 추가하면 문제가 해결되었습니다.
Teemu Leisti

Rails의 폼 헬퍼를 사용하면 자동으로 수행됩니다.
Jason FB

13

csrf 메타 태그를 포함하여 이전 앱에서 rails 3.1로 업그레이드해도 여전히 해결되지 않습니다. rubyonrails.org 블로그에서 업그레이드 팁, 특히 레이아웃의 헤드 섹션에있는 jquery 라인을 제공합니다.

$(document).ajaxSend(function(e, xhr, options) {
 var token = $("meta[name='csrf-token']").attr("content");
  xhr.setRequestHeader("X-CSRF-Token", token);
});

이 블로그 게시물에서 가져 왔습니다 : http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails .

필자의 경우 세션은 각 아약스 요청에 따라 재설정되었습니다. 위의 코드를 추가하면 문제가 해결되었습니다.


10
  1. <%= csrf_meta_tag %>레이아웃에 있는지 확인하십시오
  2. beforeSend헤더를 설정하기 위해 ajax 요청에 csrf-token을 포함 시키려면 a 를 추가하십시오 . 이것은 post요청 에만 필요 합니다.

csrf-token을 읽는 코드는에서 사용할 수 rails/jquery-ujs있으므로 다음과 같이 사용하는 것이 가장 쉽습니다.

$.ajax({
  url: url,
  method: 'post',
  beforeSend: $.rails.CSRFProtection,
  data: {
    // ...
  }
})

Rails에 이미 포함 된 것을 다시 구현하지 않고도 간단합니다. 선택한 답변이어야합니다.
jiehanzheng 2012

In Rails 5.1에서도 작동합니다 :headers: { 'X-CSRF-Token': Rails.csrfToken() }
olhor

@nathanvda, 아마도 당신은이 비슷한 질문에 대답 할 수 있습니다 : stackoverflow.com/questions/50159847/…


6

여기에서 가장 많이 투표 된 답변은 정확하지만 도메인 간 요청을 수행하는 경우 jQuery에 세션 쿠키를 전달하도록 명시 적으로 지시하지 않으면 세션을 사용할 수 없으므로 작동하지 않습니다. 이를 수행하는 방법은 다음과 같습니다.

$.ajax({ 
  url: url,
  type: 'POST',
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
  },
  xhrFields: {
    withCredentials: true
  }
});

이 비슷한 질문에 대답 할 수 있는지 물어봐도 될까요? stackoverflow.com/questions/50159847/…

5

아래와 같이 전역으로 작성할 수 있습니다.

일반적인 JS :

$(function(){

    $('#loader').hide()
    $(document).ajaxStart(function() {
        $('#loader').show();
    })
    $(document).ajaxError(function() {
        alert("Something went wrong...")
        $('#loader').hide();
    })
    $(document).ajaxStop(function() {
        $('#loader').hide();
    });
    $.ajaxSetup({
        beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))}
    });
});

커피 스크립트 :

  $('#loader').hide()
  $(document).ajaxStart ->
    $('#loader').show()

  $(document).ajaxError ->
    alert("Something went wrong...")
    $('#loader').hide()

  $(document).ajaxStop ->
    $('#loader').hide()

  $.ajaxSetup {
    beforeSend: (xhr) ->
      xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))
  }

5

죄송합니다 ..

내 application.js에서 다음 줄을 놓쳤습니다.

//= require jquery_ujs

나는 그것과 그것의 작동을 대체했다.

======= 업데이트 됨 =========

5 년 후, 나는 같은 오류로 돌아 왔고 이제는 새로운 Rails 5.1.6을 가지고 있으며이 게시물을 다시 찾았습니다. 인생의 원처럼.

문제는 Rails 5.1 이 기본적으로 jqueryjquery_ujs 에 대한 지원을 제거 하고 추가 한 것입니다.

//= require rails-ujs in application.js

다음과 같은 일을합니다.

  1. 다양한 행동에 대한 강제 확인 대화;
  2. 하이퍼 링크에서 비 GET 요청을합니다.
  3. 양식 또는 하이퍼 링크가 Ajax와 비동기식으로 데이터를 제출하도록합니다.
  4. 두 번 클릭을 방지하기 위해 제출 양식에서 제출 단추가 자동으로 비활성화됩니다. (보낸 사람 : https://github.com/rails/rails-ujs/tree/master )

그러나 왜 Ajax 요청에 csrf 토큰이 포함되어 있지 않습니까? 누군가 이것에 대해 자세히 알고 있다면 저에게 의견을 말하십시오. 알겠습니다.

어쨌든 나는 사용자 정의 js 파일에 다음을 추가하여 작동 시켰습니다 (이 코드에 도달하는 데 도움이되는 다른 답변에 감사드립니다).

$( document ).ready(function() {
  $.ajaxSetup({
    headers: {
      'X-CSRF-Token': Rails.csrfToken()
    }
  });
  ----
  ----
});

이것이 내가해야 할 일이었습니다. 이것이 나타난 이유는 기존 Rails 앱을 천천히 대체하기 위해 React 앱을 빌드하고 있기 때문입니다. 기존 앱에 많은 자바 스크립트 노이즈가 발생하기 때문에 다른 자바 스크립트 파일에 액세스하는 다른 레이아웃을 만들었지 만 포함하지 못했습니다 jquery_ujs. 그게 속임수였습니다.
Wylliam Judd

1
예, 가끔 재 작업 할 때이를 놓치면 무언가를 리팩토링하십시오. 잘못되는 것을 찾기가 어렵습니다. Rails는 수동으로 작업을 수행하지 않기 때문에 Rails는 자동으로이를 포함합니다. 우리는 이미 거기에 있다고 생각합니다. 소셜 Qn / Ans 사이트에 감사드립니다
Abhi

아마 당신은이 비슷한 질문에 대답 할 수 있습니다 : stackoverflow.com/questions/50159847/…

4

jQuery를 사용하지 않고 요청에 fetch API 와 같은 것을 사용하는 경우 다음을 사용하여 다음을 얻을 수 있습니다 csrf-token.

document.querySelector('meta[name="csrf-token"]').getAttribute('content')

fetch('/users', {
  method: 'POST',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json',
    'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')},
    credentials: 'same-origin',
    body: JSON.stringify( { id: 1, name: 'some user' } )
    })
    .then(function(data) {
      console.log('request succeeded with JSON response', data)
    }).catch(function(error) {
      console.log('request failed', error)
    })

이 비슷한 질문에 대답 할 수 있는지 물어봐도 될까요? stackoverflow.com/questions/50159847/…

4

jquery.csrf ( https://github.com/swordray/jquery.csrf )를 사용하십시오 .

  • 레일스 5.1 이상

    $ yarn add jquery.csrf
    //= require jquery.csrf
  • 레일스 5.0 이하

    source 'https://rails-assets.org' do
      gem 'rails-assets-jquery.csrf'
    end
    //= require jquery.csrf
  • 소스 코드

    (function($) {
      $(document).ajaxSend(function(e, xhr, options) {
        var token = $('meta[name="csrf-token"]').attr('content');
        if (token) xhr.setRequestHeader('X-CSRF-Token', token);
      });
    })(jQuery);


5.1에서 webpack을 사용 //= require jquery.csrf하면 작동하지 않습니까 ? 대신 pack js 파일을 사용 import 'jquery.csrf'했습니다. 뷰에 이것을 팩 태그와 함께 포함시킬 필요 는 없습니다 .
Damien Justin Šutevski

3

jQuery와 함께 자바 스크립트를 사용하여 양식에 토큰을 생성하는 경우 다음과 같이 작동합니다.

<input name="authenticity_token" 
       type="hidden" 
       value="<%= $('meta[name=csrf-token]').attr('content') %>" />

분명히, 당신은 <%= csrf_meta_tag %>Ruby 레이아웃 에 있어야합니다 .


2

jQuery가 아닌 답변이 필요한 사람들은 다음을 간단하게 추가 할 수 있습니다.

xmlhttp.setRequestHeader ( 'X-CSRF-Token', $ ( 'meta [name = "csrf-token"]'). attr ( 'content'));

여기에서 매우 간단한 예를 볼 수 있습니다.

xmlhttp.open ( "POST", "example.html", true);
xmlhttp.setRequestHeader ( 'X-CSRF-Token', $ ( 'meta [name = "csrf-token"]'). attr ( 'content'));
xmlhttp.send ();

6
선택기에 jQuery를 사용하지 않습니까?
Yule

2

나는 며칠 동안이 문제로 어려움을 겪었습니다. 모든 GET 호출이 올바르게 작동했지만 모든 PUT에 "CSRF 토큰 인증을 확인할 수 없습니다"오류가 발생합니다. nginx에 SSL 인증서를 추가 할 때까지 내 웹 사이트가 제대로 작동했습니다.

나는 마침내 nginx 설정 에서이 누락 된 줄을 발견했습니다.

location @puma { 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header Host $http_host; 
    proxy_redirect off;
    proxy_set_header X-Forwarded-Proto https;   # Needed to avoid 'WARNING: Can't verify CSRF token authenticity'
    proxy_pass http://puma; 
}

누락 된 줄 "proxy_set_header X-Forwarded-Proto https;"를 추가 한 후 모든 CSRF 토큰 오류가 종료됩니다.

잘하면 이것은 벽에 머리를 때리는 다른 사람을 도울 수 있기를 바랍니다. ㅋ



0

Rails 4.2.4를 사용하고 있는데 왜 내가 얻는 지 알 수 없었습니다.

Can't verify CSRF token authenticity

나는 레이아웃에있다 :

<%= csrf_meta_tags %>

컨트롤러에서 :

protect_from_forgery with: :exception

호출 tcpdump -A -s 999 -i lo port 3000은 헤더가 설정되어 있음을 보여주었습니다 (헤더를 설정할 필요는 없지만 ajaxSetup이미 완료되었습니다).

X-CSRF-Token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
DNT: 1
Content-Length: 125
authenticity_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

결국 쿠키가 꺼 졌기 때문에 실패했습니다. 쿠키를 사용하도록 설정하지 않으면 CSRF가 작동하지 않으므로이 오류가 표시 될 수 있습니다.


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