LoginSignup
5
0

More than 1 year has passed since last update.

Google超え(?)の安全・高速認証ができるCloudflare TurnstileをRailsに導入

Last updated at Posted at 2022-12-21

TurnstileとCHAPTCHA

今回はTurnstileとCHAPTCHAについて説明しTurnstileをRailsのアプリに導入していきたいと思います。
先日CloudflareからTurnstileという認証テストのβ版が発表され、ユーザーのプライバシーを担保し高速なUXを提供し無料で利用できるということで従来のCAPTCHAの代替となりうるのではないかとされています。TurnstileはCAPTCHAとは違いTurnstileは高性能で不視性を保つ認証テストです。認証はユーザーの目の見えないところで起こり、人間が操作していることを判断の基準にします。

Turnstile は、CAPTCHA の「ユーザーフレンドリーでプライバシーを保護する代替手段」として提示されています。プレス リリースによると、Cloudflare によると、通常、通過に平均 32 秒かかる人物の確認に使用されるインタラクティブなチャレンジが不要になり、プロセス全体が 1 秒に短縮されます

CAPTCHAの背景

CAPTHCAというのはサービスを操作しているのが人間かbotかを判別するための認証方法です。

CAPTCHAを活用すれば、botが行う自動的で行われる大量アクセスを防ぐことができスパムによるサーバーダウンや不正アカウントの作成を防ぐために開発されました。

よくあるのがサービスを使用する際によく歪んでいる文字を入力したり画像の〇〇を選択してくださいのような認証方法だと思います。

CHAPTCHAの問題点~認証~

以下のような認証方法だと一見よくわからない視覚的なパズルや歪んでいる文字を与えられた時に、一分以上もの時間が取られてしまうことがありませんか。

私時々CAPTHCA認証に失敗してしまい、AWSのログイン時に人間であるにも関わらず一定期間ログインできなくなった経験があります。
image.png

CHAPTCHAの問題点~プライバシー~

またCAPTCHAはユーザーデータを取り込みプライバシーを犠牲にするという悪評も散見されます。
一般的に使用されているGoogleのreCAPTCHAはGoogleアカウントとの連携を求められユーザー情報をGoogle側に提供してしまうことにつながります。(Googleは広告会社なので)

Turnstileの導入

image.png

サイト登録

まず初めにサイトを登録していきます。
今回はQiitaに投稿するということなのでlocalhostでCloudflareのTurnstileに登録をしました。
※本番環境のサイトキーでlocalhostを登録するのは推奨されていません
image.png

次にTurnstileのWidgetの種類を選択しSite KeyとSecret Keyを取得します。
image.png

フロントエンド

取得したサイトキーを以下のコードの引数に入れます。

app/views/users/registrations/new.html.haml
     .box-login
        .actions
        = f.submit "アカウント登録", class: "btn-text"
      .cf-turnstile.mb-2{"data-callback" => "javascriptCallback", "data-controller" => "cloudflare-turnstile", "data-sitekey" => "サイトキー"}
      .box-newusr
        = link_to "ログイン画面へ", user_session_path

バックエンド

バックエンドではprepend_before_actionを使用してユーザー登録前にTurnstileで認証を行わせます。
Turnstileはbefore_actionの前に行うアクションを行う必要があるためprepend_before_actionを使用します。

app/controllers/users/registrations_controller.rb
  prepend_before_action :validate_cloudflare_turnstile, only: [:create]

private
  def validate_cloudflare_turnstile
    validation = CloudflareTurnstile.validate(params[:"cf-turnstile-response"], request.remote_ip)
    return if validation

    self.resource = resource_class.new sign_up_params
    resource.validate
    set_minimum_password_length
    respond_with_navigational(resource) { render :new }
  end

Turnstileをdeviceで使用するためにはroutingを編集してあげる必要があります。

config/routes.rb |
# 変更前
devise_for :users

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

validateの論理を作っていきます。

models/cloudflare_turnstile.rb

require "net/http"

class CloudflareTurnstile
  SECRET_KEY = "シークレットキー".freeze
  ALL_HTTP_ERRORS = [Errno::ETIMEDOUT]
  def self.validate(payload, remote_ip)
    new(payload, remote_ip).validate
  end

 def initialize(payload, remote_ip)
    @payload = payload
    @remote_ip = remote_ip
  end

  def validate
    return false unless @payload
    response = validate_from_cloudflare
    response["success"]
  end

  private

  def validate_from_cloudflare
    retries ||= 0
    url = URI("https://challenges.cloudflare.com/turnstile/v0/siteverify")
    response = Net::HTTP.post_form(url, secret: SECRET_KEY, response: @payload, remoteip: @remote_ip)
    JSON.parse(response.body)
  rescue *ALL_HTTP_ERRORS
    retry if (retries += 1) < 3
  end
end

参考サイト

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0