reCAPTCHAとは
ボットなどによる悪質なアクセスからWebサイトを守るための機能です。
V2については以下の記事を参考してください。
https://qiita.com/amagasu1234/items/9760c2c410776fd02e12
今回はRubyOnRails環境でreCAPTCHA V3を追加してみました。
説明 | ||
---|---|---|
V1 | 歪められた文字を読み取って入力することでボットではないことを確認する。 2018年3月サービス終了 | |
V2 | 画像を選択させることで人間とボットを判別する。 | |
V3 | V1/V2とは違ってユーザー入力なし、アクセスに対する人間らしさのスコア値 (0.0 〜 1.0) でボット判別。 2018年10月29日サービス開始 |
#開発環境
rails: 5.1
macOS Mojave
IDE: RubyMine
今回のテストソースは以下のrails チュートリアルをベースに実装したので詳細内容は以下のリンクを参照してください。
https://railstutorial.jp
ログイン画面にreCAPTCHAをテストするため、以下のrails チュートリアルのOpenソースを使いました。
https://github.com/yasslab/sample_apps
#作業手順
- Google reCAPCHA管理コンソールからサイトキーとシークレットキー取得
- ヘッダーにreCAPTCHAのスクリプト追加
- ログインフォームにHidden追加
- サーバーサイド実装
#Google reCAPCHA管理コンソール
新規登録
以下のリンクから新規登録するとサイトキーとシークレットキーが発行されますので覚えておきましょう。
https://www.google.com/recaptcha/admin/create
登録完了
登録が完了すると以下のような不正リクエストの状況を確認できる管理サイトが追加されます。
#ヘッダーにreCAPTCHAのスクリプト追加
<script src="https://www.google.com/recaptcha/api.js?render=reCAPCHAサイトキー"></script>
<script>
grecaptcha.ready(function () {
grecaptcha.execute('reCAPCHAサイトキー', { action: 'contact' }).then(function (token) {
var recaptchaResponse = document.getElementById('recaptchaResponse');
recaptchaResponse.value = token;
});
});
</script>
#ログインフォームにHidden追加
ログイン画面にHidden追加
<input type="hidden" name="recaptcha_response" id="recaptchaResponse">
<% provide(:title, "Log in") %>
<h1>Log in</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(:session, url: login_path) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= link_to "(forgot password)", new_password_reset_path %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :remember_me, class: "checkbox inline" do %>
<%= f.check_box :remember_me %>
<span>Remember me on this computer</span>
<% end %>
<input type="hidden" name="recaptcha_response" id="recaptchaResponse">
<%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
#サーバーサイド実装
require 'uri'
require 'net/http'
class SessionsController < ApplicationController
RECAPTCHA_SECRET_KEY = 'reCAPTCHAコンソールからシークレットキーを入力'
RECAPTCHA_SITEVERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify'
# POST /login
def create
# siteverifyAPIを呼び出してボットかチェック
siteverify_uri = URI.parse("#{RECAPTCHA_SITEVERIFY_URL}?response=#{params[:recaptcha_response]}&secret=#{RECAPTCHA_SECRET_KEY}")
response = Net::HTTP.get_response(siteverify_uri)
json_response = JSON.parse(response.body)
# reCAPTCHAのレスポンスデータが成功かスコアが0.5以上なら人間のアクションだと判断
# スコアについては運用中変更する必要がある
if json_response['success'] && json_response['score'] > 0.5
user = User.find_by(email: params[:session][:email])
if user && user.authenticate(params[:session][:password])
if user.activated?
# Success
log_in user
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
redirect_back_or user
else
message = "Account not activated. "
message += "Check your email for the activation link."
flash[:warning] = message
redirect_to root_url
end
else
# Failure
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
else
flash.now[:danger] = '不正アクセスです。'
render 'new'
end
end
end
siteverify
APIが返すscoreが「1」に近いのがより人間のアクション、「0」に近い場合はボットの可能性が高い意味です。
これだけでGoogle reCAPTCHAが画面からのアクションを監視します。
以下の画面の右下にreCAPTCHAに保護されているのが表示されます。
3人のアカウントを事前に登録してアカウントを変えてログインしたら最初ログインに成功したユーザー以外のアカウントではログインできませんでした。
#まとめ
こんなに簡単にボットからサイトを守れるのはすごい、問題はどれぐらい正確に判断できるのかですね。
今回は実装だけやってみましたが次回はCapybaraを利用してテストしてみます。