Ruby On Rails フレームワークには、Web サービス API を公開するサーバー アプリケーションの構築を容易にする機能が含まれています。たとえば、コントローラーは次のことを行います。
respond_to :html, :json, :xml
def show
@thing = Thing.find(params[:id])
respond_with @thing
end
...両方の Web ブラウザーの「表示」アクションを処理し、HTML を返します。また、このデータ形式を指定する要求に対して、項目「@thing」を JSON または XML としてレンダリングします。
この特定の例では、GET ベースの「表示」アクションには、特別なセキュリティ対策は含まれていません。上記と同様のケースを考えてみますが、'create' や 'update' などのアクション - (シミュレートされた) PUT または (実際の) POST リクエストによってアクティブ化されるものです。これで、CSRF 保護が機能します。
ここで残念なことに、Rails は、同じドメインの Web ページ内で実行される JavaScript コードからの「API 呼び出し」(非 HTML 形式の応答) に対処するように設計されているようです。 CSRF 保護は必須です。JavaScript コードは、Rails に含まれる魔法の「メタ」タグを探し、CSRF トークンを読み取り、サーバー上で POST ベースのアクションなどを呼び出す XHR 呼び出しでそれを送信できます。
しかし、外部の呼び出し元についてはどうでしょうか? Rails が Web サイトをサポートしているが、同じヘッドエンドと通信するネイティブの iOS または Android アプリを作成したい場合はどうなるでしょうか? そのアプリはサービス呼び出しを行っています - いいですよ、Rails はこれを簡単にします - しかし、CSRF トークンを持っていないため、サーバー上のデータを変更しようとすると失敗します。同じコントローラ コードが Web ブラウザと「純粋な API」クライアントを処理するため、CSRF 保護をバイパスすることはできません。
Rails および API 呼び出しに関する CSRF の問題に関連するすべての回答は、そのような場合に別のコントローラーを使用することを想定しているようです。しかし、それはばかげています-CSRFをバイパスする特別なコントローラーで一連のコードを複製しない限り、WebページのJavaScriptコードにのみ使用される場合、「アプリをサービスとして簡単に公開できるようにする」もののポイントは何ですか非 Web クライアントを許可するには? このような追加のコントローラーは、攻撃面を増やすだけです。
RailsアプリでCSRF保護に対処するための推奨される「正しい」パターンを知っている人はいますか? 「respond_with(...)」のような組み込みのものは、遍在するフィールドとしてCSRFトークンを含むJSON / XMLオブジェクトを常に生成するなど、何も役に立ちません。私が考えることができる最善の方法は、それを自分で行うことです。たとえば、「@thing」を次のようにレンダリングします。
{
csrf: "abcdef...7890",
object: { ...JSON representation of @thing... }
}
...しかし、これはちょっとしたハックのようで、非常に多くの作業が必要であり、すべてのリクエストで最新のトークンをアナウンスすることで、world+dog の CSRF をバイパスしているようです。もっと良い方法があるはずです:-)