Rails 4 Authenticityトークン


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、またはより具体的には次の行を見ると、違いを確認できます。

Railsの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

Railsの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
Casey

6
JSON以外の呼び出しに例外を使用し、JSON呼び出し(別名API呼び出し)にnullセッションを使用する方法はありますか?
James McMahon

@JamesMcMahon before_actionフォーマットをチェックし、リクエストが検証されているかどうかを確認する独自のコードを作成できる場合があります。条件を設定する組み込みの方法は知りません。
alexcoco 2014年

1
Rails 4.1.6では、skip_before_action :verify_authenticity_tokenこれを機能させるために、APIのアプリケーションコントローラーでも指定する必要がありました。
Waseem 2014年

1
:verify_authenticy_tokenRails 4.2では、これ以上無効にする必要はありません。デフォルトはです:null_session。これは、名前が示すように、セッションなしでリクエストを提供するだけです。代わりに、APIキーを使用してリクエストを確認できます。
ロバティ2015年

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、2014

70

次の行をフォームに追加するとうまくいきました:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %>

12
api呼び出しには実際には適用されません
コートシマ

2
私の場合、Rails4を使用しています。送信ボタンをクリックしてフォームを送信できます。しかし、JSコードを介してフォームを送信すると、このエラーが発生します。そして、この答えは私のために問題を修正しました。
Chris.Zou 14

2
私のRails 4.0.8ベースのアプリの場合、=token_tag nilまたは(.erbで)書くだけで十分でした<%= token_tag nil %>
jmarceli '10

1
トークンをnilに設定して認証を無効にしているようですか?
Carlos

これを行うことは安全ですか?
エンジェルガルシア

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 2016年

次のようなメソッドを定義する必要があります: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

以下は、レールの異なるバージョンのいくつかの線です。

Rails 3

skip_before_filter:verify_authenticity_token

Rails 4

skip_before_action:verify_authenticity_token


すべてのコントローラールーチンに対してこのセキュリティ機能を無効にする場合は、application_controller.rbファイルのprotect_from_forgeryの値を:null_sessionに変更できます。

そのようです、

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

1

RailsでjQueryを使用している場合は、認証トークンを検証せずにメソッドへのエントリを許可するように注意してください。

jquery-ujsはトークンを管理できます

jquery-rails gemの一部としてすでに持っているはずですが、application.jsに含める必要があるかもしれません。

//= require jquery_ujs

これで十分です-これでajax呼び出しが機能するはずです

詳細については、https//github.com/rails/jquery-ujsを参照して ください。



0

独自のhtmlフォームを定義する場合は、セキュリティ上の理由からコントローラーに送信する必要がある認証トークン文字列を含める必要があります。Railsフォームヘルパーを使用して認証トークンを生成すると、次のようにフォームに追加されます。

<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 2014

リクエストのコンテンツが実際にはJSONである場合を除いて、その場合はJSONに設定しapplication/jsonます。
alexcoco 2014

答えはあなたが探しているものとは完全には一致しないことを理解しています。しかし、関連する回答を置く目的は、同様の「信頼性の問題」を探しているユーザーを支援することです。
amjad 14

申し訳ありませんが、誤って削除しました-「上記のソリューションでContent-Type:application / x-www-form-urlencodedを設定できます」。
amjad 14

0

私のテストはすべてうまくいきました。しかし、何らかの理由で、環境変数を非テストに設定しました。

export RAILS_ENV=something_non_test

この変数を設定解除するのを忘れたため、ActionController::InvalidAuthenticityToken例外が発生し始めました。

設定を解除した後$RAILS_ENV、テストが再び機能し始めました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.