reCAPTCHAでスパム対策をした話


2023年 04月 20日

先日スパム対策のためにreCAPTCHAをRailsアプリケーションに導入しました。

対応するにあたり、reCAPTCHAについていろいろ調べたので個人的備忘録も兼ねて記事にします。

reCAPTCHAとは

CAPTCHAという仕組みを利用した、Googleが提供するBotと人間を識別する、スパム対策サービスです。

そもそもCAPTCHAってなに

CAPTCHAは

「Completely Automated Public Turing test to tell Computers and Humans Apart」

(コンピューターと人間を区別するための完全に自動化された公開チューリングテスト)

の頭字語です。

歪んだ文字の画像を見て、テキストを入力する方式が初期のCAPTCHAだったそうです。

ですが、徐々にOCRの技術が進み、Botがより難解な画像を識別できるようになったため、最近は画像を選択する方式や、ユーザーの行動をスコア化する方式等に置き換わっています。

改めてreCAPTCHAとは

CAPTCHAという仕組みを利用した、Googleが提供するBotと人間を識別する、スパム対策サービスです。reCAPTCHAには以下の種類があります

v1

v1

歪んだ文字を表示、ユーザーがテキストを入力する方式。現在は非公開。

v2 Checkbox

ユーザーがチェックボックスをクリックし、Botの可能性がある場合、ユーザーがお題に沿った画像を選択する方式。(個人的にすごい苦手。トラクターとか難かしすぎるでしょ。。。)

v2 Invisible

v2のチェックボックスが無く、ユーザーの行動によって判断する方式。Botの疑いがある場合に、チェックボックスを表示する。

v2 Android

Android向けのreCAPTCHA。

v3

v2 Invisibleと同様にチェックボックスが無く、ユーザーの行動をスコア化して判断する方式。v2 Invisibleと違い、スコアによってどういう処理をするかは開発者に委ねられる。

reCAPTCHAは無料で利用できますが、有料のEnterprise版もあります。無料版とEnterprise版の違いはこちらを参照してください。

実際にRubyで実装してみた

今回はrecaptchaというgemを使って実装しました。https://github.com/ambethia/recaptcha

# Gemfile
gem "recaptcha"

まず、Googleのサイトから任意のreCAPTCHAタイプを選択してキーを発行します。

そして、画面に表示されたサイトキーとシークレットキーをconfigに設定します。

# config/initializers/recaptcha.rb
Recaptcha.configure do |config|
  config.site_key = "サイトキー"
  config.secret_key = "シークレットキー"
end

v2 Checkboxの場合

# app/views/recaptcha/index.html.erb
<%= form_with url: '/recaptcha' do |form| %>
  <%= form.submit "送信" %>
  <%= recaptcha_tags %>
<% end %>
# app/controllers/recaptcha_controller.rb
class RecaptchaController < ApplicationController
  def index; end

  def create
    if verify_recaptcha
      # 認証成功
    else
      # 認証失敗
    end
  end
end

認証成功時のレスポンスは以下です。

{"success"=true, "challenge_ts"="2023-03-30T08:00:00Z", "hostname"="localhost"}

v2 Invisibleの場合

# app/views/recaptcha/index.html.erb
<%= form_with url: '/recaptcha' do |form| %>
  <%= invisible_recaptcha_tags text: "送信" %>
<% end %>
# app/controllers/recaptcha_controller.rb
class RecaptchaController < ApplicationController
  def index; end

  def create
    if verify_recaptcha
      # 認証成功
    else
      # 認証失敗
    end
  end
end

認証成功時のレスポンスは以下です。

{"success"=true, "challenge_ts"="2023-03-30T08:00:00Z", "hostname"="localhost"}

v3の場合

# app/views/recaptcha/index.html.erb
<%= form_with url: '/recaptcha' do |form| %>
  <%= form.submit "送信" %>
  <%= recaptcha_v3 action: "send" %>
<% end %>
# app/controllers/recaptcha_controller.rb
class RecaptchaController < ApplicationController
  def index; end

  def create
    if verify_recaptcha(action: "send", minimum_score: 0.5)
      # 認証成功
    else
      # 認証失敗
    end
  end
end

認証成功時のレスポンスは以下です。v2の内容に加えてscoreとactionが返ります。

{"success"=>true, "challenge_ts"=>"2023-03-30T06:15:22Z", "hostname"=>"localhost", "score"=>0.9, "action"=>"send"}

minimum_scoreには0.0~1.0の間の任意のスコアをできます。スコアが高いほど人間らしいという判断です。

まとめ

  • reCAPTCHAはGoogleが提供するBot対策の仕組み
  • reCAPTCHAで利用可能なタイプは4種類ある
  • reCPATHCAをRubyで実装した