JSONリクエストで渡すCSRFトークンを取得するにはどうすればよいですか?
セキュリティ上の理由から、すべてのリクエストタイプ(JSON/XMLを含む)で RailsがCSRFトークンをチェックしている であることを知っています。
コントローラにskip_before_filter :verify_authenticity_token
を入れることはできますが、CRSF保護は失われます(お勧めできません:-))。
これに似た(まだ受け入れられていない) answer は
<%= form_authenticity_token %>
でトークンを取得します
問題はどうやって?トークンを取得するためにページのいずれかを最初に呼び出してから、Deviseで実際の認証を行う必要がありますか?または、サーバーから取得して、一貫して使用することができる(サーバー自体で手動で変更するまで)1回限りの情報ですか?
編集:
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で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トークンを送信できます。
例えば、これをあなたのsessions#createに入れてください:
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=
ドキュメント: form_authenticity_token
本当に簡単な方法。ヘッダーの変更を気にしないでください。
次のものがあることを確認してください。
<%= 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
心配なのは、Rails 3.2.3でproduction.logにCSRF警告が表示されるようになったが、投稿が失敗しないことです!攻撃から身を守るため、失敗させたい。また、フィルタbtwの前にjqueryでcsrfトークンを追加できます。
この答え の方が良い。
XMLHttpRequestを送信する前に、追加の労力(トークンが追加される)なしでCSRF-TOKEN検証を維持できます。 JQueryはありません。コピー/貼り付けして更新するだけです。
このコードを追加するだけです。
(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);
};
}());
以下を使用しました。 includeを使用しますか?そのため、コンテンツタイプがapplication/json; charset = utf-8の場合、引き続き機能しています。
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format.include? 'application/json' }
次のバージョンのRailsでも同じ問題が発生しました。
gem 'Rails'、:git => 'git://github.com/Rails/rails.git'、:branch => '3-2-stable'
3.2.2にアップデートしましたが、今ではすべてがうまく機能します。 :)
宝石「レール」、「3.2.2」
また、開発/テストモード用。
protect_from_forgery with: :exception unless %w(development test).include? Rails.env
この警告は、:null_session
を使用しているため表示されます。Rails 4.1では、with:
オプションが指定されていない場合、デフォルトで動作します。
protect_from_forgery
今夜、同じ問題に遭遇しました。発生する理由は、最後のcsrfトークンにサインインすると無効になるためです。私がしたことは、あなたのapp/views/devise/sessions/create.js.rbの$("meta[name=csrf-token]").attr('content', '<%= form_authenticity_token %>');
です。
今では有効なcsrf-tokenがあります:)