##二重サブミットをどうにか防止したかった。
具体的には下記のようなケースで防止したかったです。
- ブラウザバックか戻るボタンで戻って、再度保存
- 完了ページでブラウザリロード
###contorllerの処理
def new
@inquiry = Inquiry.new
end
def confirm
@inquiry = Inquiry.new(inquiry_params)
render :new unless @inquiry.valid?
end
def done
@inquiry = Inquiry.new(inquiry_params)
if params[:back].present?
render :new
return
end
if @inquiry.save
#メールを送付
InquiryMailer.send_inquiry_to_user(@inquiry).deliver
else
render :new
end
end
入力画面▶️確認画面▶️完了画面の順に移り変わります。
確認画面と完了画面に関してはPostで表示させています。
完了画面にリダイレクトさせるPRGパターンもあるようですが、今回は採用していません。
##個人的に思いついた二重サブミット対策
完了画面のPost処理の最後にセッションのauthenticity_tokenのパラメータを削除する。
session[:_csrf_token] = nil
RailsはデフォルトでCSRF対策をしてくれます。
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
end
上記によってファームを生成する際にauthenticity_tokenがフォームとセッションに発行され、その二つが合っているかを判断します。
よってPostの最後にセッション側のトークンを削除することで、以降フォームとセッションのトークン情報が合致しなくなるためリロードやブラウザバックをしてもInvalidAuthenticityTokenとしてエラーになります。これで二重サブミットの対策になるんじゃないかと。(InvalidAuthenticityTokenの場合のエラーページを表示させるようにすればユーザーも戸惑わないはず)
セッションのトークンを削除することによるCSRF対策の影響も恐らくないのではと。
##最後に
まだまだRailsに関しては初心者で、他の方法が思いつかなかったので他の人は普段どうやって実装しているのか知りたいです!!!!!!
ぜひ教えてください!!!!!!!!!!!!