更新日:
【Rails】 reCAPTCHAをWebフォームに導入〜スパムからサイトを守ろう
reCAPTCHAとは、ユーザー登録などWebフォームの登録がプログラムで自動で行われているか、人間が手動で行っているかを判別することができるシステムのことです。
みなさんが一度は目にしたことのあるスパムによる登録を防ぐGoogleが提供しているサービスです。
導入することにより、プログラムによってユーザー登録が自動で作成されるのを防ぐことができます。Googleに登録することで無料で使うことができるので、ぜひ試してみてください。
reCAPTCHAを導入しよう
この章では、reCAPTCHAの導入方法について解説します。
googleで利用登録をしよう
まずはgoogleでreCAPTCHAを使うための登録をしましょう。
googleにログインした状態でこちらのリンクから登録画面に移動します。
すると下記の画面になるので、右上の「admin console」をクリックします。
「新しいサイトを登録」画面から下記のように入力をし、「送信」をクリックします。
すると下の画像のようにサイトキーとシークレットキーが作成されます。
こちらのキーは後からいつでも確認することができます。
環境変数を設定しよう
次に今作成したキーを環境変数としてセットしていきます。
アナリティクスの画面右上の歯車のアイコンをクリックしましょう。
設定画面が表示されるので「reCAPTCHAのキー」をクリックします。
すると下の画像のように先程のキーが表示されます。
これでサイトキーとシークレットキーを確認することができました。
この2つのキーを設定ファイルに記述しますが、このままの形でキーを記述するとgithubなどにファイルをアップした時に、第三者が確認できてしまいます。
ですのでこのような場合は環境変数としてキーを管理します。
それでは環境変数を定義しましょう。
環境変数はdotenv-rails
というgemを使って管理すると便利です。
まずは、dotenv-rails
をインストールする為に、Gemfile
に下記を追加してbundle installします。
1
gem 'dotenv-rails'
次に環境変数を定義するファイルを作成します。
ターミナルで下記のコマンドを実行してください。
1
$ touch .env
このコマンドによりルートに.envファイル
を作成することができました。
次に今作成した.envファイル
を編集していきます。
1
2
3
4
5
6
RECAPTCHA_SITE_KEY = 先ほど確認したサイトキー
RECAPTCHA_SECRET_KEY = 先ほど確認したシークレットキー
# 例
RECAPTCHA_SITE_KEY = ALdym5iVtaoJcZgAVAAAAAELsT0JryvoL_nnd1zJ
RECAPTCHA_SECRET_KEY = ALdymgbUvFBHWXGrAtgsyoqTVAAAAAChuTKn9M1n
これで環境変数を定義することができました。
dotenv-rails
の詳しい使い方についてはdotenv-railsの導入方法と使い方を理解して環境変数を管理しよう!を参考にしてください。
gemをインストールしよう
次にrailsでreCAPTCHAを使うためgemをインストールします。
Gemfileに下記のコードを追記しましょう。
1
gem 'recaptcha', require: "recaptcha/rails"
その後、bundle installコマンドを実行します。
必要なファイルを作成しよう
次に必要なファイルを作成します。
configフォルダ内のinitializersフォルダにrecaptcha.rb
というファイルを作成します。
コマンドで作成する場合は下記のコマンドを実行します。
1
$ touch config/initializers/recaptcha.rb
作成したrecaptcha.rb
ファイルに下記の記述をします。
1
2
3
4
Recaptcha.configure do |config|
config.site_key = ENV['RECAPTCHA_SITE_KEY']
config.secret_key = ENV['RECAPTCHA_SECRET_KEY']
end
サイトキーとシークレットキーに先程定義した環境変数を代入します。
ちゃんと環境変数が読み込まれているかコンソールで確認してみましょう。
rails c
コマンドでコンソールモードにして変数の中身を確認してみましょう。
1
2
3
4
5
[1] pry(main)> ENV['RECAPTCHA_SITE_KEY']
=> "サイトキーが表示"
[2] pry(main)> ENV['RECAPTCHA_SECRET_KEY']
=> "シークレットキーが表示"
登録したキーがしっかりと表示されていれば大丈夫です。
これで準備は完了です。
実際にサイトで表示してみよう
それではビューファイルにreCAPTCHを表示させる記述を行っていきます。
ビューファイルに記述しよう
表示したいビューファイルに下記のコードを記述します。
今回はdeviseを使ってユーザーを登録する場合を例にとってみます。
deviseのビューファイルはデフォルトだと編集ができないので、下記のコマンドでビューファイルを作成します。
1
$ rails g devise:views
新規登録のビューファイルはviews/devise/registrations
フォルダの中にあるnew.html.erb
ファイルです。
※views/devise/sessions
フォルダ内にもnew.html.erb
ファイルがありますが、こちらはログイン用のビューファイルなので間違えないようにしてください
このビューファイルに下記のコードを追記します。
1
2
# filename: app/views/devise/registrations/new.html.erb | コードの記述
<%= recaptcha_tags %>
今回は送信ボタンの上にこの一行を追記してみます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# filename: app/views/devise/registrations/new.html.erb | コードの記述
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<%= recaptcha_tags %> <%# このコードを追記する %>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
実際に下記のように表示されているか確認してみましょう。
承認されないときは登録できないようにしよう
これで表示をさせることができましたが、今のままだとチェックをしていなくても登録ができてしまうので、チェックをしていない場合は登録できないようにする必要があります。
そのためには、コントローラーにチェックをしたかどうか判別するメソッドを追加します。今回はdeviseを使ってユーザー登録する時を例にあげてみます。
まずは、deviseのコントローラーをカスタマイズするためのコントローラーを作成します。
1
$ rails g devise:controllers users
すると「controllers」の「users」の中にdeviseクラスを継承した下記のコントローラーファイルが作成されます。
- confirmations_controller.rb
- omniauth_callbacks_controller.rb
- passwords_controller.rb
- registrations_controller.rb
- sessions_controller.rb
- unlocks_controller.rb
今回はサインアップのとき動くコントローラーなのでregistrations_controller.rb
を編集していきます。
まずはreCAPTCHがチェックされているかどうか判別するメソッドを定義します。
verify_recaptchaメソッド
を使うとチェックしていればtrue
が、されていなければfalse
が返ってくるのでこれを利用します。
deviseの公式サイトを参考にしてコードを追記します。
registrations_controller.rb
のクラスの中のコードは全てコメントアウトされている状態です。
コメントアウトされている最後のコードの下に下記のコードを追記してください。(unlessの使い方は、こちらの「unless文とは?」を参考にしてください。)
1
2
3
4
5
6
7
8
9
private
def check_captcha
unless verify_recaptcha
self.resource = resource_class.new sign_up_params
resource.validate # Look for any other validation errors besides reCAPTCHA
set_minimum_password_length
respond_with_navigational(resource) { render :new }
end
end
次にここで作成したcheck_captchaメソッド
をユーザー登録が行われる前に実行させたいのでprepend_before_action
を使います。
prepend_before_action
はbefore_actionが実行される前に実行するメソッドです。
1
2
3
class Users::RegistrationsController < Devise::RegistrationsController
# 上のコードの下に下記の一行を追記
prepend_before_action :check_captcha, only: [:create]
次に先程作成したコントローラーを使うため、ルーティングを編集します。
1
2
3
4
5
6
7
# 変更前
devise_for :users
# 変更後
devise_for :users, controllers: {
registrations: 'users/registrations'
}
これでユーザー登録時にreCAPTCHを使うことができるようになりました。
実際にチェックされていないときには登録画面に戻るか確認してみましょう。
チェックをしていないとこのように新規登録画面が表示されました。
ではチェックを入れたら登録できるか確認してみましょう。
このようにチェックをすると無事登録することができました。
フラッシュメッセージを表示させよう
チェックをしていないと登録できないようになりましたが、登録できないときにはなぜ登録できなかったのかメッセージを表示させたいですね。
そんなときにはフラッシュメッセージを使います。
ビューファイルのフラッシュメッセージを表示させたい場所に下記のコードを追記してください。
1
<%= flash[:recaptcha_error] %>
実際に投稿してフラッシュメッセージが表示されるか確認してみます。
今回はreCAPTHAのチェックボックスの上にフラッシュメッセージを表示させるようにしました。
このようにエラーメッセージを表示させることができました。
ただエラーメッセージが英語なので日本語で表示させたいですね。
この場合はregistrations_controller.rb
内でcheck_captcha
メソッド内のコードを下記のように編集します。
1
2
3
4
5
# 変更前
unless verify_recaptcha
# 変更後
unless verify_recaptcha(message: "reCAPTCHAのチェックをしてください")
実際に確認してみましょう。
このようにフラッシュメッセージが日本語になっていればOKです。フォームの項目を日本語化したいという方は、こちらのI18n入門書で日本語化に挑戦してみてください。
このように簡単に実装できるので、スパムで困っている方はぜひ実装をしてみてはいかがでしょうか。Ruby on Railsについて体系的に深く学びたい方はこちらの参考書1冊を手元に置いておくと良いでしょう。
この記事のまとめ
- reCAPTCHAはプログラムによるユーザー登録を防ぐためのシステムです
- Googleで登録をすれば無料で使えます
- スパムで困っている方はぜひ実装しておきましょう