joppot

コピペで絶対動く。説明を妥協しない

プログラミング

railsのsimple-captcha gemを使用してform_forを使ったフォームを画像認証する

投稿日:

Pocket

fea

概要

みなさんこんにちはcandleです。公に開かれたフォームはスパムや総当り攻撃を受けやすいです。
そこで、画像認証を導入して、悪意のあるフォームを拒否してみましょう。

simple-captchaは本当にシンプルで、表示される画像は大文字のアルファベットのみです。これは画像認証が読みづらくて、ユーザーが離れる事を避ける事ができる一方で、セキュリティ的には多少低いでしょう。下の図をみて、もっと複雑な画像認証がしたい場合は他の方法を試してください。

siplecaptchaimage

前提
railsの環境が整っている

twitterbootstrap gem を使用した環境で説明して行きます。twitterbootstrap gem事態はデザインのライブラリみたいなものなので、必ずしも入れる必要はありません。

SPONSORED LINK


simple-captcha gemをインストールする

Gemfileに下の記述を書きましょう。

gem 'simple_captcha', :git => 'git://github.com/galetahub/simple-captcha.git'

simplecaptchagemfile

保存したら、gemをインストールします。

bundle install

gemインストール完了です。


simple-captchaのセットアップ

simple-captchaはフォームで画像認証された値をデータベースにあるデータと参照して認証をしています。そのため、simple-captcha用のテーブルを用意します。

下のコマンドでsimple-captchaを作成します。

rails generate simple_captcha

createsimplecaptcha

マイグレーションファイルをデータベースに反映させます。

rake db:migrate

次に、app/controllers/application.rb のApplicationControllerクラスの中に下のソースを貼り付けます。

include SimpleCaptcha::ControllerHelpers

includeapplicationcontroller

これでセットアップ完了です。

サンプルのscaffoldを作成する

下のコマンドを実行してください。

rails g scaffold Memo title:string description:text

rake db:migrate

Memo scaffoldが完成しました。

twitterbootstrap gemを反映させる

もしも、twitterbootstrap gemが入っているなら、下のコマンドでスタイルを反映させます。

rails generate bootstrap:install static

rails g bootstrap:layout application

rails g bootstrap:themed Memos

テーマが反映されました。


ビューを変更する

フォームに関するビューを変更します。今回の例で言えば、memosの_form.html.erbを変更します。app/views/memos/_form.html.erbを開いて、フォームタグの中に下の記述を書きます。

<div class="form-group">
  <%= f.label "Simple-Captcha",:class => 'control-label' %>
  <div class="controls">
    <%= f.simple_captcha :label => "上の文字を記入してください",:placeholder => "ここに入力" %>
  </div>
</div>

こんな感じ
simplecaptchaform

下のように表示されたでしょうか?

newmemoandimage

ビューの変更は以上です。

モデルを編集する

form_forを使用してフォームを作った場合、データベースのカラムと紐付いていない値をフォームから投げる場合は擬似的な値を受け取ることを宣言しなくてはいけません。

simple-captchaから送られてくるcaptcha_key,とcaptchaを受けれる様に、モデルに必要事項を記述します。
今回の例で説明しますと、app/models/memo.rbを開いて、下の記述を

class Memo < ActiveRecord::Base
end

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

class Memo < ActiveRecord::Base
  attr_accessor :captcha_key, :captcha
end

にして保存しましょう。

コントローラーを変更する

ストロングパラメーターで値を許可する

シンプルキャプチャのフォームから送られてきた値を受けるために、
ストロングパラメーターで許可する必要があります。下の2つの値を許可しましょう。
:captcha_key, :captcha

例えば、memosコントローラーmemo_params関数の場合は下のようになります。

def memo_params
  params.require(:memo).permit(:title, :description,:captcha_key, :captcha)
end

フォームの値を受けるアクションを編集

フォームから送られてきた値を処理してデータベースに収めるアクションの中に、下の文章を書いて、画像認証の判定をします。

if simple_captcha_valid?
  #データベースに値を収める処理
end

もしも、このif文が正しく通れば、画像認証ができているということです。

例えば、scaffoldの場合、createdアクションにこのif文を適応させたければ、下の様にします。

def create
  @memo = Memo.new(memo_params)
  if simple_captcha_valid?
    respond_to do |format|
      if @memo.save
        format.html { redirect_to @memo, notice: 'Memo was successfully created.' }
        format.json { render action: 'show', status: :created, location: @memo }
      else
        format.html { render action: 'new' }
        format.json { render json: @memo.errors, status: :unprocessable_entity }
      end
    end
  else
    render action: 'new'
  end
end


simple_captcha_valid?をオーバライドする

ここからが本番です。実はこのsimple_capcha_valid?関数はsimple-captcha gemに書かれているのですが、この関数がフォームから送られてくる値の参照し方が下のようになっています。

params[:captcha]
params[:captcha_key]

ところが、form_forから送られて来る場合は下のような参照の仕方をしないといけません。
:memoの記述は各自のコントローラーの名前になります。

params[:memo][:captcha]
params[:memo][:captcha_key]

つまり、編集しないと正しい値をsimple-captcha gemが取得できないのです。

gemを直接書き換えるのはよくないといわれています。
なので、このsimple_captcha_valid?関数をオーバライドして使えるようにしましょう。

config/environment.rbを開きます。ファイルの一番下に下の記述をコピペします。
何度も言いますが、今回のサンプルを使っていない場合は[:memo]のところは各々のコントローラー名にしてください。

#simplecaptchaのオーバーライド
module SimpleCaptcha  
  module ControllerHelpers
    def simple_captcha_valid?
      return true if Rails.env.test?
      if params[:memo][:captcha]
        data = SimpleCaptcha::Utils::simple_captcha_value(params[:memo][:captcha_key] || session[:captcha])
        result = data == params[:memo][:captcha].delete(" ").upcase
        SimpleCaptcha::Utils::simple_captcha_passed!(session[:captcha]) if result
        return result
      else
        return false
      end
    end
  end
end

保存したら、サーバを再起動しましょう。
これで、simple-captchaが使えます。

実際に使ってみる

新しいmemoを作成する画面に行き、正しい値を入力します。

postmemousingimageauth

「Create Memo」を押すと、入力した値が正しければ、データベースに新しいレコードが保存されます。

excellentimageauth

認証できました。

まとめ

form_forを使うと少々面倒な事になりますが、これでなんとか画像認証ができます。
もしも、これよりも良い方法がある場合はコメント欄などによろしくお願いします。

スポンサードリンク

「為になったなぁ」と思ったら、シェアお願いします。

-プログラミング
-

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

CakePHPでhelloworld

概要 CakePHPでプログラミングのお約束helloworldを行いましょう。 helloworldとは動作確認も含めた、一番最初に書くプログラムコードです。 だいたいはhello worldと単純 …

memcachedサーバとruby on railsのdalliを使用してセッションを管理する

概要 みなさんこんにちはcandleです。今回はmemcachedサーバを利用してrailsのセッションを管理してみたいと思います。 一般にrailsでセッション管理をしていると、ブラウザのcooki …

railsのaws-sdk gemを使ってs3に画像ファイルをフォームからアップロードする

概要 みなさんこんにちはcandleです。比較的難しいrailsからs3に画像をアップロードする方法を試してみましょう。 一般にサーバ環境にはスケーラビリティ(アクセスの規模に応じて、動的にサーバを動 …

gemspecのsummary項目とdescription項目の違いに付いて

概要 みなさんこんにちはcandleです。 gemを自作していたら、gemspecのところでsummaryとdescriptionの違いが分からなかったので、 調べたら、公式ページに書いてあったので、 …

railsのfluent-logger gemを使ってユーザーのアクセスをfluentdサーバに収集する

概要 みなさんこんにちはcandleです。前回からfluentd関連の記事を続けていますが、今回辺りから実用的な使い方を書いていきたいと思います。 fluentdと言えば、ビックデータで扱うようなデー …

  • English
  • 日本語

プロフィール


ベンチャー企業のCTOをやってます。大学時代にプログラミングを始め、javaから入門し、C++へて、PHPへと進み、会社ではRailsを使用。自動化が大好きなプログラマー

スポンサードリンク

アーカイブ