1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

uuidを使用したブラウザバックによる連続投稿への対策

Last updated at Posted at 2020-10-03

概要

入力、確認、完了画面と遷移する、よくあるフォームを作っていて、uuidによるブラウザバック対策を試したのでメモ。
ブラウザバックそのものというよりは、完了から確認画面にブラウザバックして何度も投稿させるのを防ぐことを目的にしている。

方針

DBのテーブルに、uuidを保存するカラムを追加する。
すると完了画面の時点でuuidも保存されるが、パラメーターの中に残っているuuidがテーブル内に既に存在する場合は、エラー画面にリダイレクトさせる。

実装

1. カラム追加

uuidを保存するためのカラムを足す。

20201003xxxxxx_add_uuid_to_sample.rb
class AddUuidToSamples < ActiveRecord::Migration[5.2]
  def change
    add_column :samples, :uuid, :string
  end
end

2. コントローラー

newアクションのタイミングで、uuid を発行しておく。confirm では、キャッシュを保存できないよう no-store を設定。
confirm と create で uuid が既に存在していないかを確認し、存在していればエラー画面に遷移させる。

Cache-Controlの参考
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Cache-Control

sample_controller.rb
before_action :verify_validate, only: [:confirm, :create]

def new
  @sample_form.uuid = ::SecureRandom.uuid
end

def confirm
  response.headers['Cache-Control'] = 'no-store'
end

def create
  if sample_form.save
    redirect_to complete_sample_path
  else
    render :error
  end
end

private

  def sample_form
    @sample_form ||= ::SampleForm.new(Sample.new)
  end

  def verify_validate
    render :new sample_form.validate(params[:sample])
    return redirect_to error_sample_path if Sample.exists?(uuid: sample_form.uuid)
  end

3. ビュー

最後に、new と confirm に対応するビューに、hidden_fieldを仕込んでおく。
uuid の生成は、newアクションだけで行うようにして、以降は hidden_field でバケツリレーさせる。

new.slim
= form_for sample_form, url: confirm_samples_path do |f|
  # 省略
  = f.hidden_field :uuid
  = f.button '確認'
confirm.slim
= form_for sample_form, url: confirm_samples_path do |f|
  # 省略
  = f.hidden_field :uuid
  = f.button '送信'
1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?