Rails 4 진품 토큰


198

진품 토큰 문제가 발생했을 때 새로운 Rails 4 앱 (Ruby 2.0.0-p0)을 작업하고있었습니다.

respond_to클래스 메소드를 사용하여 json에 응답하는 컨트롤러를 작성하는 동안 을 사용하여 레코드를 만들려고 할 때 예외 createActionController::InvalidAuthenticityToken발생 하기 시작한 작업에 도달했습니다 curl.

나는 내가 설정했는지 확인 -H "Content-Type: application/json"하고 데이터를 설정 -d "<my data here>"했지만 여전히 운이 없다.

Rails 3.2 (Ruby 1.9.3)를 사용하여 동일한 컨트롤러를 작성하려고 시도했지만 진위 토큰 문제가 없었습니다. 나는 주변을 검색했고 Rails 4에서 진품 토큰에 약간의 변화가 있음을 알았습니다. 내가 이해 한 것으로부터, 더 이상 자동으로 양식에 삽입되지 않습니까? 이것이 HTML이 아닌 내용 유형에 영향을 미친다고 생각합니다.

HTML 양식을 요청하지 않고 진위성 토큰을 채운 다음 해당 토큰으로 다른 요청을하지 않고도이 문제를 해결할 수 있습니까? 아니면 완전히 명백한 것을 완전히 놓치고 있습니까?

편집 : 방금 아무것도 변경하지 않고 비계를 사용하여 새 Rails 4 앱에서 새 레코드를 만들려고했는데 동일한 문제가 발생하여 내가 한 것이 아니라고 생각합니다.

답변:


277

방금 알아 낸 것 같아요 (새) 기본값을 변경했습니다

protect_from_forgery with: :exception

protect_from_forgery with: :null_session

의 의견에 따라 ApplicationController.

# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.

의 소스를 살펴 request_forgery_protecton.rb보거나 다음 줄 을 보면 차이를 확인할 수 있습니다 .

에서 레일 3.2 :

# This is the method that defines the application behavior when a request is found to be unverified.
# By default, \Rails resets the session when it finds an unverified request.
def handle_unverified_request
  reset_session
end

에서 레일 4 :

def handle_unverified_request
  forgery_protection_strategy.new(self).handle_unverified_request
end

다음을 호출 합니다 .

def handle_unverified_request
  raise ActionController::InvalidAuthenticityToken
end

20
: with 옵션을 모두 제거 할 수 있습니다. : null_session이 기본값입니다. api.rubyonrails.org/classes/ActionController/…
Casey

6
JSON이 아닌 호출에 대해 예외를 사용하고 JSON 호출 (일명 API 호출)에 대해 널 세션을 사용하는 방법이 있습니까?
James McMahon

@JamesMcMahon before_action형식을 확인하고 요청이 확인되었는지 직접 작성할 수 있습니다 . 조건을 설정하는 내장 된 방법을 모르겠습니다.
alexcoco

1
레일 4.1.6에서는 skip_before_action :verify_authenticity_tokenAPI의 응용 프로그램 컨트롤러 를 지정 하고이 작업을 수행해야했습니다.
Waseem

1
:verify_authenticy_tokenRails 4.2에서는 더 이상 비활성화 할 필요가 없습니다 . :null_session이름에서 알 수 있듯이 기본값은 이며 세션없이 요청을 제공합니다. 대신 API 키를 통해 요청을 확인할 수 있습니다.
lobati

72

csrf 보호 기능을 끄는 대신 다음 코드 줄을 양식에 추가하는 것이 좋습니다.

<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %> 

form_for 또는 form_tag를 사용하여 양식을 생성하는 경우 양식에 위의 코드 행을 자동으로 추가합니다.


9
양식을 작성하는 경우 좋은 조언이지만 JSON을 사용하여 API를 호출하는 것이 문제입니다.
James McMahon

1
그럼에도 불구하고, 이것은 핸들 바를 사용하는 동안 코드를 직접 작성하는 것에 대한 질문에 대한 답변입니다!
David Routen

70

양식에 다음 줄을 추가하면 나에게 도움이되었습니다.

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

12
api 통화에는 실제로 적용되지 않습니다
courtsimas

2
제 경우에는 Rails4를 사용하고 있습니다. 제출 버튼을 클릭하여 양식을 제출할 수 있습니다. 그러나 JS 코드를 통해 양식을 제출하면이 오류가 발생합니다. 그리고이 답변은 문제를 해결했습니다.
Chris.Zou

2
내 레일 4.0.8 기반의 앱은 쓰기에 충분했다 =token_tag nil(.erb에서) 또는<%= token_tag nil %>
jmarceli

1
토큰을 nil로 설정하여 인증을 사용하지 않는 것 같습니다.
카를로스

이 작업을 수행해도 안전합니까?
Angel Garcia

33

API를 독점적으로 구현하지 않는 한 일반적으로 CSRF 보호를 해제하는 것이 좋지 않다고 생각합니다.

ActionController 에 대한 Rails 4 API 문서를 볼 때 컨트롤러 또는 메소드 기반에서 위조 방지 기능을 끌 수 있음을 발견했습니다.

예를 들어 사용할 수있는 방법에 대해 CSRF 보호를 끄려면

class FooController < ApplicationController
  protect_from_forgery except: :index

이것은 Rails 4에서 나를 위해했습니다. 삭제하려고 시도한 후에 오류가 발생했습니다. ^^
zero_cool

9

같은 문제를 겪었습니다. 컨트롤러에 추가하여 수정했습니다.

      skip_before_filter :verify_authenticity_token, if: :json_request?

정의되지 않은 메소드`json_request? ' # <SettingsController : 0x000000030a54a8>에 대한 아이디어가 있습니까?
Deano

def json_request?와 같은 메소드를 정의해야합니다. request.format.json? 끝
Jai Kumar Rajput

7

시도해 보았 니?

 protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }



2

이러한 기능은 보안 및 위조 방지 목적으로 추가되었습니다.
그러나 귀하의 질문에 대답하기 위해 몇 가지 입력 사항이 있습니다. 컨트롤러 이름 뒤에이 줄을 추가 할 수 있습니다.

이렇게

class NameController < ApplicationController
    skip_before_action :verify_authenticity_token

다음은 다른 버전의 레일에 대한 몇 가지 라인입니다.

레일 3

skip_before_filter : verify_authenticity_token

레일 4 :

skip_before_action : verify_authenticity_token


모든 컨트롤러 루틴에 대해이 보안 기능을 사용하지 않으려면 protect_from_forgery 의 값을 변경할 수 있습니다 려면 application_controller.rb 파일에서 을 : null_session 으로 .

이렇게

class ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session
end

1

레일과 함께 jQuery를 사용하는 경우 진위성 토큰을 확인하지 않고 메소드 입력을 허용해야합니다.

jquery-ujs가 토큰을 관리 할 수 ​​있습니다

jquery-rails gem의 일부로 이미 포함되어 있지만 application.js에 포함시켜야 할 수도 있습니다.

//= require jquery_ujs

그게 전부입니다-아약스 전화가 작동합니다

자세한 내용은 https://github.com/rails/jquery-ujs를 참조하십시오.



0

자신이 html 양식을 정의하는 경우 보안상의 이유로 컨트롤러에 전송해야하는 인증 토큰 문자열을 포함해야합니다. rails form helper를 사용하여 진위성 토큰을 생성하면 다음과 같이 양식에 추가됩니다.

<form accept-charset="UTF-8" action="/login/signin" method="post">
  <div style="display:none">
    <input name="utf8" type="hidden" value="&#x2713;" />
    <input name="authenticity_token" type="hidden" value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
  </div>
    ...
</form>

따라서 문제에 대한 해결책은 authenticity_token 필드를 추가하거나 보안을 손상시키는 대신 레일 형식 도우미를 사용하는 것입니다.


1
원래 질문에 대한 답변은 아니지만 답변 해 주셔서 감사합니다. 이 질문은 JSON 요청에 응답하는 것에 대한 질문이지만 스크래치에서 시작하는 HTML 양식에 대한 솔루션을 제공하고 있습니다. JSON 요청 (API 생각)을 수행 할 때 HTML 양식을 제출하지 않으며 인증 토큰에 쉽게 액세스하지 못할 수 있습니다.
alexcoco

요청의 내용이 실제로 JSON이 아닌 경우로 설정하십시오 application/json.
alexcoco

나는 그 대답이 당신이 찾고있는 것이 아니라는 것을 이해합니다. 그러나 관련 답변을 제공하는 목적은 유사한 "정품 문제"를 찾는 사용자를 돕기위한 것입니다.
amjad

죄송합니다. 실수로 제거했습니다.- "위의 솔루션으로 Content-Type : application / x-www-form-urlencoded을 (를) 설정할 수 있습니다".
amjad

0

모든 테스트가 제대로 작동했습니다. 그러나 어떤 이유로 든 환경 변수를 테스트하지 않도록 설정했습니다.

export RAILS_ENV=something_non_test

ActionController::InvalidAuthenticityToken예외 가 발생 하기 때문에이 변수를 설정 해제하는 것을 잊었습니다 .

설정을 해제 한 후 $RAILS_ENV테스트가 다시 시작되었습니다.

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