LoginSignup
3
0

More than 3 years have passed since last update.

【Rails】個人的に思いついた二重サブミット対策【意見も募集】

Last updated at Posted at 2019-08-29

二重サブミットをどうにか防止したかった。

具体的には下記のようなケースで防止したかったです。
- ブラウザバックか戻るボタンで戻って、再度保存
- 完了ページでブラウザリロード

参考:さいきょうの二重サブミット対策

contorllerの処理

inquiries_controller.rb
  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でのCSRFtoken発行/検証のロジック

最後に

まだまだRailsに関しては初心者で、他の方法が思いつかなかったので他の人は普段どうやって実装しているのか知りたいです!!!!!!

ぜひ教えてください!!!!!!!!!!!!

3
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0