2016-06-28 13 views
0

My Railsアプリケーションは、ユーザー入力をAJAX経由で文字列化されたJSONとしてコントローラに渡すパブリック向きのフォームを備えています。フォームはオフラインで使用するように設計されているため、最初のフォームページ以外のフォームページへの訪問は、ブラウザのキャッシュから(キャッシュマニフェストを使用して)提供されます。私はフォームのページに移動する前にブラウザの履歴がクリアされていない限りフォーム提出が422 unprocessable entityエラーを返す問題を抱えています...ユーザーが1つのフォームの提出を行うことができると言います。その後のすべての投稿は422履歴を消去してフォームに戻ってキャッシュを更新します。残念ながら、それは飛ぶつもりはありません。Rails/AJAXキャッシュフォームの提出 - 422未処理のエンティティ

私はRailsのセキュリティに関して多大な経験をしていませんが、これはCSRFの保護と関連していることと、最初のフォームページを訪問したときに失効したCSRFトークンが合格。

私のAJAX要求はそうのように表示されます。現時点では

$.ajax({ 
    url: "post/submission", 
    type: "POST", 
    dataType: "json", 
    beforeSend: function(xhr) {xhr.setRequestHeader("X-CSRF-Token", $("meta[name='csrf-token']").attr("content"))}, 
    data: {"post" : postParameter}, 
    success: function(response){ 
     window.location = '/post/approval'; 
    } 
}); 

、レイアウトページには<%= csrf_meta_tags %>を含み、そして私は、アプリケーションのコントローラに標準protect_from_forgery with: :exceptionを持っています。

フォーム自体は公開されていますが、の後にユーザーログインが必要です。送信ボタンをクリックすると、有効なログインなしで送信が成功しません。 。

この問題を回避するための安全な方法はありますか?私はそれは言うまでもないと確信していますが、私は自分の履歴をクリアし、すべての投稿の後にフォームを再キャッシュすることはできません。

+0

CSRF保護を維持するには、フォームを提示するときにトークンを再生成する必要があります。 '<%= hidden_​​field_tag:authenticity_token、form_authenticity_token%>'はそれを行います。ページがキャッシュから表示されたときのajaxコール。もっと見る[ここ](http://stackoverflow.com/questions/8503447/rails-how-to-add-csrf-protection-to-forms-created-in-javascript)と[ここ](http:// stackoverflow .com/questions/829046/how-do-i-detect-if-a-user-has-a-page-back-buttonを使用して) –

+0

うーん...私が言及しておかなければならないもう一つのことは、フォームヘルパーなどで標準のRailsファッションにフォームが組み込まれていないということです。実際、フォームはHTMLセンスのフォームではありませんユーザー入力はJSON文字列にコンパイルされ、AJAXはコントローラに渡されて解析され、DBに挿入されます。本当に 'hidden_​​field_tag'を置く場所はありません。私はあなたが含まれている2番目のリンクに私のためのいくつかの良いソリューションがあるかもしれないと思う - 私はそれらをテストし、私は何かを得ることができるかどうかをお知らせします。あなたの時間をありがとう。 – skwidbreth

+0

もちろん、テンプレートのレンダリングの一部として行っても、ajax呼び出しで転送しても、 'form_authenticity_token'の結果をフロントエンドに渡すだけで済みます。そこからPOSTペイロードに含めることができます。 –

答えて

1

JavaScriptからPOSTリクエストを送信しながらCSRF保護を維持するには、現在の認証トークンをフォームのペイロードまたはリクエストヘッダーに指定する必要があります。

ブラウザキャッシュからページが読み込まれると、その認証トークンが古くなる可能性があるため、バックエンドからリフレッシュする必要があります。これを行う1つの方法は、イベントを検出し、バックエンドでform_authenticity_tokenメソッドによって生成される新しいトークンを取得するためのajaxリクエストを実行することです。

受信した認証トークンは、その後のJavaScript POST要求に使用できます。

キャッシュからロードされているページを検出する手法は、 in this StackOverflow answer