すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】 reCAPTCHAをWebフォームに導入〜スパムからサイトを守ろう

ぴっかちゃん
ぴっかちゃん

reCAPTCHAとは、ユーザー登録などWebフォームの登録がプログラムで自動で行われているか、人間が手動で行っているかを判別することができるシステムのことです。

reCAPTCHA

みなさんが一度は目にしたことのあるスパムによる登録を防ぐGoogleが提供しているサービスです。

導入することにより、プログラムによってユーザー登録が自動で作成されるのを防ぐことができます。Googleに登録することで無料で使うことができるので、ぜひ試してみてください。

reCAPTCHAを導入しよう

この章では、reCAPTCHAの導入方法について解説します。

googleで利用登録をしよう

まずはgoogleでreCAPTCHAを使うための登録をしましょう。
googleにログインした状態でこちらのリンクから登録画面に移動します。
すると下記の画面になるので、右上の「admin console」をクリックします。

登録画面

「新しいサイトを登録」画面から下記のように入力をし、「送信」をクリックします。

新しいサイトを登録

すると下の画像のようにサイトキーとシークレットキーが作成されます。

登録完了

こちらのキーは後からいつでも確認することができます。

環境変数を設定しよう

次に今作成したキーを環境変数としてセットしていきます。
アナリティクスの画面右上の歯車のアイコンをクリックしましょう。

設定をクリック

設定画面が表示されるので「reCAPTCHAのキー」をクリックします。

設定画面

すると下の画像のように先程のキーが表示されます。

キーの確認

これでサイトキーとシークレットキーを確認することができました。
この2つのキーを設定ファイルに記述しますが、このままの形でキーを記述するとgithubなどにファイルをアップした時に、第三者が確認できてしまいます。

ですのでこのような場合は環境変数としてキーを管理します。

それでは環境変数を定義しましょう。
環境変数はdotenv-railsというgemを使って管理すると便利です。

まずは、dotenv-railsをインストールする為に、Gemfileに下記を追加してbundle installします。

Gemfile | gemの追加
1
gem 'dotenv-rails'

次に環境変数を定義するファイルを作成します。
ターミナルで下記のコマンドを実行してください。

ターミナル | .envファイルの作成
1
$ touch .env 

このコマンドによりルートに.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に下記のコードを追記しましょう。

Gemfile | gemの追加
1
gem 'recaptcha',  require: "recaptcha/rails"

その後、bundle installコマンドを実行します。

必要なファイルを作成しよう

次に必要なファイルを作成します。
configフォルダ内のinitializersフォルダにrecaptcha.rbというファイルを作成します。

コマンドで作成する場合は下記のコマンドを実行します。

ターミナル | ファイルの作成
1
$ touch config/initializers/recaptcha.rb

作成したrecaptcha.rbファイルに下記の記述をします。

config/initializers/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文とは?」を参考にしてください。)

app/controllers/users/registrations_controller.rb | メソッドの定義
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_actionbefore_actionが実行される前に実行するメソッドです。

app/controllers/users/registrations_controller.rb | prepend_before_actionを記述
1
2
3
class Users::RegistrationsController < Devise::RegistrationsController
  # 上のコードの下に下記の一行を追記
  prepend_before_action :check_captcha, only: [:create]

次に先程作成したコントローラーを使うため、ルーティングを編集します。

config/routes.rb | ルーティングの編集
1
2
3
4
5
6
7
# 変更前
devise_for :users

# 変更後
devise_for :users, controllers: {
  registrations: 'users/registrations'
}

これでユーザー登録時にreCAPTCHを使うことができるようになりました。

実際にチェックされていないときには登録画面に戻るか確認してみましょう。

登録できない

チェックをしていないとこのように新規登録画面が表示されました。
ではチェックを入れたら登録できるか確認してみましょう。

登録できる

このようにチェックをすると無事登録することができました。

フラッシュメッセージを表示させよう

チェックをしていないと登録できないようになりましたが、登録できないときにはなぜ登録できなかったのかメッセージを表示させたいですね。
そんなときにはフラッシュメッセージを使います。

ビューファイルのフラッシュメッセージを表示させたい場所に下記のコードを追記してください。

app/views/devise/registrations/new.html.erb | コードの記述
1
<%= flash[:recaptcha_error] %>

実際に投稿してフラッシュメッセージが表示されるか確認してみます。
今回はreCAPTHAのチェックボックスの上にフラッシュメッセージを表示させるようにしました。

エラー表示

このようにエラーメッセージを表示させることができました。
ただエラーメッセージが英語なので日本語で表示させたいですね。
この場合はregistrations_controller.rb内でcheck_captchaメソッド内のコードを下記のように編集します。

app/controllers/users/registrations_controller.rb | メソッドの定義
1
2
3
4
5
# 変更前
  unless verify_recaptcha

# 変更後
  unless verify_recaptcha(message: "reCAPTCHAのチェックをしてください")

実際に確認してみましょう。

メッセージが日本語になっている

このようにフラッシュメッセージが日本語になっていればOKです。フォームの項目を日本語化したいという方は、こちらのI18n入門書で日本語化に挑戦してみてください。

このように簡単に実装できるので、スパムで困っている方はぜひ実装をしてみてはいかがでしょうか。Ruby on Railsについて体系的に深く学びたい方はこちらの参考書1冊を手元に置いておくと良いでしょう。

この記事のまとめ

  • reCAPTCHAはプログラムによるユーザー登録を防ぐためのシステムです
  • Googleで登録をすれば無料で使えます
  • スパムで困っている方はぜひ実装しておきましょう