Google reCAPTCHA v3
導入の流れ
- サイトを登録してサイトキーとシークレットキーを発行する
- フロントエンドでsubmit時にトークンを発行する
- サーバサイドでスコアを評価する
フロントエンドでsubmit時にトークンを発行する
ログインフォームにreCAPTCHAのトークン用のフィールドを追加し、ログイン時にreCAPTCHAのトークンを発行して、ログインパラメータと合わせてサーバ側に送信するようにします。
(以下のサンプルはslimで書かれています)
= form_with url: signup_path, local: true, html: { name: "signupForm" } do |f| = f.email_field :email, required: true = f.password_field :password, required: true = hidden_field_tag :g_recaptcha a#signupSubmit ログイン script src="https://www.google.com/recaptcha/api.js?render=reCAPTCHA_site_key" javascript: grecaptcha.ready(() => { let form = document.querySelector("[name=signupForm]"); if (!form) { return; } form.querySelector("#signupSubmit").addEventListener("click", () => { grecaptcha.execute("reCAPTCHA_site_key", { action: "login" }).then((token) => { const recaptchaField = document.querySelector('#g_recaptcha'); recaptchaField.value = token; form.submit(); }); }); });
サーバサイドでスコアを評価する
以下のmoduleをapp/controllers/concern
等に配置し、controllerでincludeして利用します。
module GoogleRecaptcha VERIFY_ENDPOINT = "https://www.google.com/recaptcha/api/siteverify" def recaptcha_valid_token?(token, min_score) result = recaptcha_verify(token) Rails.logger.info result return false if !result["success"] result.fetch("score", 0.0) >= min_score end def recaptcha_verify(token) req = new_verify_request(token) http = Net::HTTP.new(verify_url.host, verify_url.port) http.use_ssl = verify_url.is_a?(URI::HTTPS) res = http.request(req) return { "success" => false } if res.code != "200" JSON.parse(res.body) end def verify_url @verify_url ||= URI.parse(VERIFY_ENDPOINT) end def new_verify_request(token) req = Net::HTTP::Post.new(verify_url) req.set_form_data(verify_parameters(token)) req end def verify_parameters(token) { secret: "reCAPTCHA_secret_key", response: token, } end end
controller側のサンプルコードはこちらです。
class SessionsController < ApplicationController include GoogleRecaptcha # GET /signin def new; end # POST /sessions def create if recaptcha_valid_token?(params[:g_recaptcha], 0.5) # ログイン処理 else # reCAPTCHAのスコアがしきい値より低かった場合の処理 end end end