rails-json 고안 요청에 대한 "경고 : CSRF 토큰 인증을 확인할 수 없습니다"
JSON 요청으로 전달할 CSRF 토큰을 검색하려면 어떻게해야합니까?
보안상의 이유로 Rails가 모든 요청 유형 (JSON / XML 포함) 에서 CSRF 토큰 을 확인하고 있다는 것을 알고 있습니다.
컨트롤러에 넣을 수는 skip_before_filter :verify_authenticity_token
있지만 CRSF 보호 기능을 잃을 것입니다 (권장하지 않음 :-)).
이 비슷한 (여전히 받아 들여지지 않음) 대답 은 다음을 제안합니다.
다음을 사용하여 토큰 검색
<%= form_authenticity_token %>
문제는 어떻게? 토큰을 검색하기 위해 내 페이지 중 하나를 먼저 호출 한 다음 Devise로 실제 인증을 수행해야합니까? 아니면 내 서버에서 가져 와서 지속적으로 사용할 수있는 일회성 정보입니까 (서버 자체에서 수동으로 변경할 때까지)?
수정 :
Rails 4에서는 아래 주석에서 @genkilabs가 제안한 것을 사용합니다.
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
내장 된 보안 기능을 완전히 끄는 대신 CSRF 토큰없이 무언가가 서버에 도달했을 때 존재할 수있는 모든 세션을 종료합니다.
skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }
이렇게하면 적절하게 표시된 json 게시물 / 올리기에 대한 CSRF 검사가 해제됩니다.
예를 들어 iOS에서 "parameters"가 매개 변수 인 NSURLRequest에 다음을 설정합니다.
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json"
forHTTPHeaderField:@"content-type"];
[request setValue:@"application/json"
forHTTPHeaderField:@"accept"];
[request setHTTPBody:[NSData dataWithBytes:[parameters UTF8String]
length:[parameters length]]];
성공적으로 로그인 한 후 사용자 지정 헤더를 사용하여 CSRF 토큰을 보낼 수 있습니다.
예를 들어, 이것을 세션에 넣으십시오.
response.headers['X-CSRF-Token'] = form_authenticity_token
CSRF 토큰을 제공하는 샘플 로그인 응답 헤더 :
HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Connection: Keep-Alive
Content-Length: 35
Content-Type: application/json; charset=utf-8
Date: Mon, 22 Oct 2012 11:39:04 GMT
Etag: "9d719d3b9aabd413c3603e04e8a3933d"
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12)
Set-Cookie: [cut for readability]
X-Csrf-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw=
X-Request-Id: 178746992d7aca928c876818fcdd4c96
X-Runtime: 0.169792
X-Ua-Compatible: IE=Edge
이 토큰은 다시 로그인하거나 (API를 통해 지원하는 경우 로그 아웃 할 때까지) 유효합니다. 클라이언트는 로그인 응답 헤더에서 토큰을 추출하고 저장할 수 있습니다. 그런 다음 각 POST / PUT / DELETE 요청은 로그인시받은 값으로 X-CSRF-Token 헤더를 설정해야합니다.
CSRF 토큰이있는 샘플 POST 헤더 :
POST /api/report HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Type: application/json; charset=utf-8
Cookie: [cut for readability]
Host: localhost:3000
User-Agent: HTTPie/0.3.0
X-CSRF-Token: PbtMPfrszxH6QfRcWJCCyRo7BlxJUPU7HqC2uz2tKGw=
정말 가장 간단한 방법입니다. 헤더 변경에 신경 쓰지 마십시오.
다음을 확인하십시오.
<%= csrf_meta_tag %>
당신의 layouts/application.html.erb
다음과 같이 숨겨진 입력 필드를 수행하십시오.
<input name="authenticity_token"
type="hidden"
value="<%= form_authenticity_token %>"/>
또는 jquery ajax 게시물을 원하는 경우 :
$.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);
}
});
기본적으로 json 데이터를 게시 할 때 유효한 authenticity_token 필드를 데이터에 추가 post
하면 경고가 사라집니다.
이 방법으로 오류를 해결했습니다.
class ApplicationController < ActionController::Base
protect_from_forgery
skip_before_action :verify_authenticity_token, if: :json_request?
protected
def json_request?
request.format.json?
end
end
출처 : http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
What's worrying is that in Rails 3.2.3 we now get the CSRF warning in production.log but the post does not fail! I want it to fail as it protects me from attacks. And you can add the csrf token with jquery before filter btw:
http://jasoncodes.com/posts/rails-csrf-vulnerability
I have used the below. Using include? so if the content type is application/json;charset=utf-8 then it is still working.
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format.include? 'application/json' }
This answer is better.
You get to keep the CSRF-TOKEN validation with no extra effort (the token is appended) before any XMLHttpRequest send. No JQuery, no nothing just copy/paste and refresh.
Simply add this code.
(function() {
var send = XMLHttpRequest.prototype.send,
token = $('meta[name=csrf-token]').attr('content');
XMLHttpRequest.prototype.send = function(data) {
this.setRequestHeader('X-CSRF-Token', token);
return send.apply(this, arguments);
};
}());
I had the same issue with the following version of Rails:
gem 'rails', :git => 'git://github.com/rails/rails.git', :branch => '3-2-stable'
I updated to 3.2.2 and everything works fine for me now. :)
gem 'rails', '3.2.2'
I ran into the same issue tonight. The reason that happens is because when you sign in the last csrf-token is no longer valid. What I did was: $("meta[name=csrf-token]").attr('content', '<%= form_authenticity_token %>');
in your app/views/devise/sessions/create.js.rb.
Now it does have a valid csrf-token :) I hope it helps
Also for development/test mode.
protect_from_forgery with: :exception unless %w(development test).include? Rails.env
This warning shows because you are using :null_session
, in Rails 4.1 it works by default if no with:
options specified.
protect_from_forgery
this is not a bug. It's supposed to be checked on every non-GET request. https://github.com/rails/rails/issues/3041
'Programing' 카테고리의 다른 글
Eclipse에서 단어를 선택하는 단축키 (0) | 2020.10.05 |
---|---|
별도의 문자열에서 전체 경로 문자열을 (안전하게) 만드는 방법은 무엇입니까? (0) | 2020.10.05 |
Raspberry Pi에서 SSH 연결이 거부 됨 (0) | 2020.10.05 |
새 스레드의 WebBrowser 컨트롤 (0) | 2020.10.05 |
Firefox에서 추가 버튼 간격 / 패딩 제거 (0) | 2020.10.05 |