真正性トークンの問題に遭遇したとき、新しいRails 4アプリ(Ruby 2.0.0-p0)で作業していました。
(respond_to
クラスメソッドを使用して)jsonに応答するコントローラーを作成しているときに、create
を使用してレコードを作成しようとしたときに、ActionController::InvalidAuthenticityToken
例外を取得し始めたcurl
アクションに到達しました。
-H "Content-Type: application/json"
を設定し、-d "<my data here>"
でデータを設定したことを確認しましたが、それでも運はありません。
Rails 3.2(Ruby 1.9.3)を使用して同じコントローラーを作成しようとしましたが、認証トークンの問題はまったくありませんでした。私は周りを検索しましたが、Rails 4.の認証トークンにいくつかの変更があることがわかりました。私が理解したところから、それらはもはやフォームに自動的に挿入されません。これは何らかの形で非HTMLコンテンツタイプに影響していると思われます。
HTMLフォームをリクエストし、認証トークンを取得してから、そのトークンで別のリクエストを行うことなく、これを回避する方法はありますか?または、私は完全に明らかな何かを完全に見逃していますか?
編集:新しいRails 4アプリで、何も変更せずにscaffoldを使用して新しいレコードを作成しようとしましたが、同じ問題にぶつかりました。した。
私はちょうどそれを考え出したと思います。 (新しい)デフォルトを変更しました
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
のソース、またはより具体的には次の行を見ると違いがわかります。
In 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
In Rails 4 :
def handle_unverified_request
forgery_protection_strategy.new(self).handle_unverified_request
end
これは 以下 と呼ばれます:
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
Csrf保護をオフにする代わりに、次のコード行をフォームに追加することをお勧めします。
<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %>
もしあなたがformを生成するためにform_forやform_tagを使っているなら、それは自動的にフォームに上記のコード行を追加します。
次の行をフォームに追加するとうまくいきました。
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
APIを排他的に実装していない限り、一般的にCSRF保護を無効にするのは良いとは思いません。
Rails 4 APIのドキュメントで ActionController を見ると、コントローラごとまたはメソッドごとに偽造防止を無効にできることがわかりました。
例えば、あなたが使うことができるメソッドのためにCSRF保護をオフにするために
class FooController < ApplicationController
protect_from_forgery except: :index
同じ問題に遭遇しました。私のコントローラに追加することでそれを修正しました:
skip_before_filter :verify_authenticity_token, if: :json_request?
試しましたか?
protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }
この公式ドキュメント - apiの偽造防止を適切に無効にする方法について説明します http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
これはRailsのセキュリティ機能です。このコード行を次の形式で追加してください。
<%= hidden_field_tag :authenticity_token, form_authenticity_token %>
ドキュメントはここにあります: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html
これらの機能は、セキュリティと偽造防止の目的で追加されました。
しかし、あなたの質問に答えるために、ここにいくつかの入力があります。コントローラ名の後にこれらの行を追加することができます。
そのようです、
class NameController < ApplicationController
skip_before_action :verify_authenticity_token
これはRailsのさまざまなバージョン用の行です。
Rails
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
Formタグにauthenticity_token: true
を追加してください
RailsでjQueryを使用している場合は、信憑性トークンを検証せずにメソッドへの入力を許可することには注意してください。
jquery-ujsがあなたのためにトークンを管理できます
あなたはすでにjquery-Rails gemの一部としてそれを持っているべきですが、application.jsにそれを含める必要があるかもしれません。
//= require jquery_ujs
これで、必要なことはすべて完了しました。これで、Ajax呼び出しは機能するはずです。
詳細については、以下を参照してください。 https://github.com/Rails/jquery-ujs
私のテストはすべてうまくいきました。しかし、何らかの理由で環境変数をテストしないように設定しました。
export Rails_ENV=something_non_test
私はActionController::InvalidAuthenticityToken
例外を受け始めたので、この変数の設定を解除するのを忘れました。
$Rails_ENV
の設定を解除した後、私のテストは再び働き始めました。
あなたがあなた自身のhtmlフォームを定義するとき、あなたは認証トークン文字列を含まなければなりません、それはセキュリティ上の理由からコントローラに送られるべきです。信憑性トークンを生成するためにRailsフォームヘルパーを使用する場合は、次のようにformに追加されます。
<form accept-charset="UTF-8" action="/login/signin" method="post">
<div style="display:none">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA=">
</div>
...
</form>
そのため、この問題の解決策は、セキュリティを犠牲にするのではなく、authenticicity_tokenフィールドを追加するか、Railsのフォームヘルパーを使用することです。