はてなブログの Googleフォームに reCaptcha を導入

当サイトには Googleフォームを利用したフォームメールを設置していますが、最近スパムメールが多くなってきましたので何か対策が必要になってきました。

お問い合わせ - IMUZA.com



はてなブログに Googleフォームを設置

Googleフォームのテーマではなく、はてなブログで使用しているテーマ内にフォームを設置する方法の記事です。


Google reCaptcha

「私はロボットではありません」にチェックするように促されるアレです。

f:id:ausnichts:20200213191753j:plain

reCAPTCHA: Easy on Humans, Hard on Bots


上のは v2 ですが、現在は v3 になっているようです。v3 がどういうものかわかっていませんので v2 でやってみます。

reCaptcha の考え方は、事前に発行されたサイトキーを使ったトークンをサーバーに送り、サーバーでは事前に発行されたシークレットキーを使ってトークンをチェックするということになります。

ですので、サーバー側の実装が必須になり、はてななどブログサービスでは実質的には使うことができません。ただ、クライアント(ブログ)側でトークンが発行されたかどうか、つまりボットかどうかをチェックすることだけは可能です。

効果があるかどうかはわかりませんが、一度やってみましょう。


まず、サイトキーとシークレットキーを取得します。


reCAPTCHA: Easy on Humans, Hard on Bots に行き、右上の+アイコンをクリックしサイトを登録します。

f:id:ausnichts:20200213170554j:plain


フォームに reCaptcha ウィジェットをレンダリング

reCaptcha のサイトにドキュメントがあります。

reCAPTCHA v2  |  Google Developers


<html>
  <head>
    <title>reCAPTCHA demo: Simple page</title>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
  </head>
  <body>
    <form action="?" method="POST">
      <div class="g-recaptcha" data-sitekey="your_site_key"></div>
      <br/>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>


https://www.google.com/recaptcha/api.js を読み込み、フォーム内に <div class="g-recaptcha" data-sitekey="your_site_key"></div> の htmlコードを入れるだけです。ただし、はてなの場合はデフォルトで api.js が読み込まれていますので htmlコードを挿入すればそれだけで reCaptcha ウィジェットがレンダリングされます。


クライアントサイトでバリデーション

reCaptcha ウィジェットが作成したトークンはクライアント側でも grecaptcha.getResponse() で取得することができます。この値は reCaptcha の認証を通っていない場合は空になりますので、送信ボタンをクリックした時にこの値をチェックすればいいことになります。


reCaptcha を導入した Googleフォームのコードはこうなります。もちろん、name属性、action属性、サイトキーはご自身のものに差し替えてください。

<script>
function showThxMessage(){
   var email = document.myForm.elements['entry.94116415'].value;
   if(email !== ''){
       var thxDiv = document.getElementById('thxMessage');
       thxDiv.getElementsByTagName('span')[0].innerHTML = email;
       document.myForm.reset();
       document.getElementById('formWrapper').style.display = 'none';
       thxDiv.style.display = 'block';
   }
}
function checkRecaptcha() {
  var response = grecaptcha.getResponse();
  if(response.length == 0) { 
    //reCaptcha 未認証
    document.getElementById('recaptcha-error').innerHTML = "reCaptchaにチェックを入れてください";
    return false;
  }
  else { 
    //reCaptch 認証済み
    document.myForm.submit();
  }
}
</script>
<div id="formWrapper"><form action="https://docs.google.com/forms/d/e/1FAIpQLSf34P577G_wSnWra6sfde0xGEirpor-Opk_EsDs4Z5CSYa6ng/formResponse" method="post" name="myForm" target="dummyIframe" onsubmit="return checkRecaptcha();">
        <label>メールアドレス</label>
        <p style="font-size:.8em;color:#999;">※配信可能なメールアドレスを入力してください. 自動返信メールがエラーとなる場合はサイト管理人へも配信されません.</p>
        <input type="email" name="entry.94116415" value="" required pattern="^(([-\w\d]+)(\.[-\w\d]+)*@([-\w\d]+)(\.[-\w\d]+)*(\.([a-zA-Z]{2,5}|[\d]{1,3})){1,2})$" />
        <label>お問い合わせ内容</label>
        <textarea required name="entry.1106124689"></textarea>
        <div class="g-recaptcha" data-sitekey="6LcZdtgUAAAAAIAhLVgmFuc97NQfRmrsILG9daWw"></div>
        <div style="margin-top:10px; color:red;" id="recaptcha-error"></div>
        <input style="margin-top:10px;" type="submit" value="送信">

        <iframe name="dummyIframe" style="display:none;" onload="showThxMessage();"></iframe>
    </form>
</div>
<div id="thxMessage" style="display:none;">
    お問い合わせありがとうございました。<br />
    <span style="color:red;"></span> 様あてのメールでお答えいたします。<br /><br />
    また自動返信メールをお送りいたしましたのでご確認ください。<br />
    メールが届いていない場合はお答えメールも届きませんので、迷惑メールとなっていないかなどご確認ください。<br /><br />
    --<br />
    IMUZA.com
</div>


サーバー側(Google Apps Script)

サーバー側での認証は次の記事にあります。

www.imuza.com