スパムコメント防止に simple_captcha を使う
ブログにはコメント機能がつきもの 。ということで、このブログにもちゃんとコメント機能はつけています。しかし、誰にでもコメントを書き残せるようにしてしまうとスパムコメントが書き込まれることになるでしょう。かといって、アカウント認証で制限してしまうと、アカウントの登録やログインが面倒くさくなり、気軽にコメントを書いてもらえなくなります。
このサイトにおいては、少量のスパムコメントならちょこちょこっと手作業で削除する事にし、プログラムによる大量のスパムコメントに対しては、書き込まれないように対策を講じることにしました。その対策として、 CAPTCHA という画像認証の仕組みを使います。Ruby on Rails 用のプラグインで CAPTCHA機能を実現するものにはいくつかありますが、当サイトでは simple_captcha を使う事にしました。
simple_captcha について
simple_captcha は以下の特徴を持っています(詳しくは、 公式サイト でご確認ください)。
- 色々な画像のスタイルが選べる(ランダムで自動選択も可能)
- 3レベルの画像の複雑さが選べる
- 生成する画像はアルファベットか数字かを選べる
- 画像をファイルシステムに保存しない(シークレットコードはデータベースに保存)
- データベースに保存されている古いシークレットコードは、1時間経過したら自動的に削除される
- 画像と認証コードの入力フォームが部分テンプレートで提供されているので、カスタマイズしやすい
simple_captcha をインストール
※ simple_captcha は Rails 2.0 未満のバージョンでも動作します。しかし、当エントリでは説明しておりません。必要であれば、 公式サイト 等を参照してください
コマンドラインで以下のコマンドを実行するとインストールされます。
ruby script/plugin install svn://rubyforge.org/var/svn/expressica/plugins/simple_captcha
または、SVNリポジトリから取得します。
svn co svn://rubyforge.org/var/svn/expressica/plugins/simple_captcha simple_captcha
SVN リポジトリから取得した後は、simple_captcha ディレクトリごと、アプリケーションディレクトリの vendor/plugins の下に置きます。
その他に必要なもの
RMagick が必要です。インストールされていなければ、これもインストールしておきます。
simple_captcha をセットアップ
コマンドラインで、以下のコマンドを実行します。
rake simple_captcha:setup
続けて、以下のコマンドを実行します。
rake db:migrate
以下のように、config/routes.rb ファイルに simple_captcha の設定内容を追加(追加するのは、 map.simple_captcha 行のみです)します。
ActionController::Routing::Routes.draw do |map| map.simple_captcha '/simple_captcha/:action', :controller => 'simple_captcha' end
以下のように、app/controllers/application.rb ファイルの ApplicationController に SimpleCaptcha::ControllerHelpers の組み込みを追加(追加するのは include 行のみです)します。
class ApplicationController < ActionController::Base include SimpleCaptcha::ControllerHelpers end
simple_captcha をアプリケーションで利用する
simple_captcha の使い方には、 コントローラーベース と モデルベース の 2種類あります。
コントローラーベースはモデルに関連しないフォームで利用します。例えば、当サイトの場合 お問い合わせフォーム が該当します(但し、お問い合わせフォームには CAPTCHA 機能は組み込んでおりません)。
一方、今回のケースのようにコメント投稿などモデル関連のフォームで利用する場合にモデルベースを使います。そうすることで、validater のチェックや、保存が一つのメソッドで済ませる事ができます。
具体的には、以下のようにして varidator によるチェックと CAPTCHA チェックがおこなわれます。 validate? メソッドの呼び出しだけでは、CAPTCHA チェックはおこなわれません。
if @comment.validate_with_captcha? # validator によるチェック成功時の処理 end
保存処理は以下のようになります。こうすることで、 comment モデル に設定されているバリデーション、CAPTCHA チェック、保存処理がおこなわれます。 save メソッドの呼び出しだけでは、CAPTCHA チェックがおこなわれません。
if @comment.save_with_captcha # 保存成功時の処理 end
コントローラーベースでの使い方
CAPTCHA 画像とキー入力フォームを表示したいテンプレートに、以下のように show_simple_captcha ヘルパー呼び出しを追加します。
<%= show_simple_captcha %>
コントローラーでは、以下の処理を用いて CAPTCHA 画像と入力されたキーとが一致するかどうかをチェックします。
if simple_captcha_valid? # チェック OK の時の処理 else # チェック失敗時の処理 end
モデルベースでの使い方(コメントモデルへの組み込み)
コメントモデル ( app/models/comment.rb ) を編集し、以下のように apply_simple_captcha を組み込みます。
class Comment < ActiveRecord::Base apply_simple_captcha end
コメントコントローラー ( app/controllers/comments_controller.rb ) も修正します。
コメントは投稿のみで編集が出来ないように(当サイトでは)作っていますので、コントローラーの create メソッドのみを修正します。
以下のようにコメントモデルの save メソッドを呼び出している箇所を、
@comment = Comment.new(params[:comment])
@comment.commentable = @entry
respond_to do |format|
if @comment.save
flash[:notice] = 'Comment was successfully created.'
save_with_captcha メソッド呼び出しに変更します。
@comment = Comment.new(params[:comment])
@comment.commentable = @entry
respond_to do |format|
if @comment.save_with_captcha
flash[:notice] = 'Comment was successfully created.'
コメントフォームのCAPTCHA 画像とキー入力フォームを表示したい箇所に、以下のように show_simple_captcha ヘルパー呼び出しを追加します。今回は コメントモデル に組み込みたいので、 :object => "comment" と入力します。
<%= show_simple_captcha :object => "comment" %>
CAPTCHA フォームの表示オプション指定
コントローラーベースとモデルベース、どちらの場合もテンプレートで show_simple_captcha ヘルパーを呼び出していますが、オプションを指定すれば表示される画像等を変更できます。
- :label
- フォームに表示するラベルを指定します。デフォルトは、"type the code from the image" です。
- :image_style
-
画像のスタイルを指定します。指定可能なスタイルは以下の通りです。
- simply_blue
- simply_red
- simply_green
- charcoal_grey
- embosed_silver
- all_black
- distorted_black
- almost_invisible
デフォルトは、’simply_blue’ です。’random’ を指定すると、上記スタイルの中から一つが選ばれます。
- :distortion
- 画像の複雑さを指定します。指定出来る値は、’low’, ‘medium’, ‘high’ とあり、’low’ はほとんど変化がありません。’high’ だと人間でもかなり読みづらくなります。デフォルトは、’low’ です。
- :code_type
- 文字の種類を指定出来ます。’numeric’ を指定すると、数字のみ6桁の画像になります。それ以外の値を指定した場合や、このオプションを指定しない場合はアルファベット6桁の画像になります。
当サイトでは、以下のように呼び出しています。
<%= show_simple_captcha :object => "comment", :distortion => 'medium',
:image_style => 'simply_red',
:label => '画像に書かれた文字を入力してください' %>
モデル組み込みのオプション指定
さきほど、コメントモデルに組み込んだ apply_simple_captcha ですが、オプションを指定する事で、エラーメッセージの変更が可能になります。
- :message
- チェックエラーの時に表示するメッセージを指定します。デフォルトメッセージは次のものです。"Secret Code did not match with the Image"
- :add_to_base
- true を設定するとエラーメッセージを base object に追加します。その結果、エラーメッセージにフィールド名を表示しなくなります(false の場合は、「Captcha 画像と入力キーが一致しません。」のようにエラーメッセージの先頭にフィールド名が表示されます)。
例えば、当サイトのコメントモデルには、以下のように書かれています。
class Comment < ActiveRecord::Base apply_simple_captcha :message => '画像と入力キーが一致しません。', :add_to_base => true end
テンプレートの書き換え
当サイトのテンプレート ( app/views/simple_captcha/_simple_captcha.erb )は、以下のようにごっそり書き換えています。デフォルトのテンプレートだと IE7 と Firefox で表示が異なりますのでそのままでは使えないです。
<div id='simple_captcha'> <%= label_tag "captcha", "画像認証" %>(必須)<br/> <%= @simple_captcha_options[:image] %><br/> <%= @simple_captcha_options[:field] %> <%= @simple_captcha_options[:label] %> </div>
