IMUZA.com

Xserver<<WordPress(ConoHa)<<はてなブログ

ホーム / Google / Google Apps Script(GAS) で reCaptcha 認証をする

Google Apps Script(GAS) で reCaptcha 認証をする

2020/02/20 Google, はてなブログ

前記事「はてなブログの Googleフォームに reCaptcha を導入」に書きましたように当サイトのお問い合わせフォームメールにスパムがくるようになりましたので reCaptcha を導入しようと、その記事ではクライアント側だけのバリデーションを試しましたが、やはりこれでスパムをはじくのは難しく、なんとかサーバー側、この場合は Google Apps Script(GAS) ですので、GAS で認証チェックできないかとやってみました。

可能です。成功しました!

  • reCaptcha 認証とは
  • Google Apps Script で reCAPTCHA 認証
    • クライアント側
    • サーバー(GAS)側
  • 結果と問題点

reCaptcha 認証とは

詳しくは、「はてなブログの Googleフォームに reCaptcha を導入」をご覧ください。

  • reCaptcha でサイトを登録し、サイトキーとシークレットキーを取得する
  • フォーム内に <div class="g-recaptcha" data-sitekey="your_site_key"></div> を仕込む
  • ユーザが reCaptcha をチェックするとサイトキー(your_site_key)を使ったトークンが作成される
  • フォームデータとともにトークンをサーバーに送る
  • サーバー側でトークンとシークレットキーを使って認証チェックを行う
  • 認証の結果によって振り分ける

といった流れかと思います。

で、クライアント側で reCaptcha がチェックされたか、つまりトークンが作成されたかを調べればボットを防げるかと思いましたが、考えてみれば、ボットはいちいちそのサイトに来てスパムを送るわけではなく、フォームの action属性や input要素を取得して自動化しているわけですから、クライアントの Javascript なんかじゃ防げないですね。

Google Apps Script で reCAPTCHA 認証

ということで、Google Apps Script(GAS)で reCAPTCHA 認証をするためには、

  • トークンを GAS に送る
  • GAS で認証する
  • 可能なら結果をクライアントに返す

という過程を経れば認証が可能になります。

クライアント側

考え方は汎用のものですが、下のコードははてなブログにお問合せフォームを設置するためのものです。「はてなブログの Googleフォームに reCaptcha を導入」をご覧ください。

<script>
function checkRecaptcha() {
  var response = grecaptcha.getResponse();
  if(response.length == 0) { 
    //トークンなし
    document.getElementById('recaptcha-error').innerHTML = "reCaptchaにチェックを入れてください";
    return false;
  }
  else { 
    //トークンあり
    document.myForm.elements['下のフォーム内のinput要素のhidden型'].value = response;
    document.myForm.submit();
  }
}
function showThxMessage(){
   var email = document.myForm.elements['下のフォーム内のメールのinput要素'].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';
   }
}
</script>
<div id="formWrapper">
<form action="https://docs.google.com/forms/d/e/グーグルフォームのアクセス先" method="post" name="myForm" target="dummyIframe" onsubmit="return checkRecaptcha();">
<label>メールアドレス</label>
<p style="font-size:.8em;color:#999;">※配信可能なメールアドレスを入力してください. 自動返信メールがエラーとなる場合はサイト管理人へも配信されません.</p>
<input type="email" name="メールのinput要素" 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="お問い合わせ内容のinput要素"></textarea>
<div class="g-recaptcha" data-sitekey="reCaptchのサイトキー"></div>
<div style="margin-top:10px; color:red;" id="recaptcha-error"></div>
<input type="hidden" name="recaptcha名などで作成したinput要素" value="">
<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>

フォーム内に hidden型の input要素を仕込んでおき、ユーザーが reCaptchaにチェックを入れることで作成されたトークンを grecaptcha.getResponse() で hidden型に入れて GASに送ります。

サーバー(GAS)側

同じく verifyCaptcha() は汎用のものですが、スクリプト自体は上記クライアント側に対応したものです。

参考記事
reCAPTCHA with Google Apps Script – Google Apps Script Tutorial

//Secret key
var secret = 'reCaptcha のシークレットキー';
function verifyCaptcha(arg){
var payload = {
'secret' : secret,
'response': arg
}
var url = 'https://www.google.com/recaptcha/api/siteverify';
var resp = UrlFetchApp.fetch(url, {
payload : payload,
method : 'POST'
}).getContentText();
return JSON.parse(resp).success;
}
function submitForm(e){
var itemResponses = e.response.getItemResponses();
for (var i = 0; i < itemResponses.length; i++) {
var question = itemResponses[i].getItem().getTitle();
var answer = itemResponses[i].getResponse();
if (question == 'メールアドレス') var userMail = answer;
if (question == 'お問い合わせ内容') var userMessage = answer;
if (question == 'recaptcha') var recaptcha = answer;
}
var resp = verifyCaptcha(recaptcha);
if(resp)
{
// 自動返信メール
var subject = 'お問い合わせ内容確認';
var body = 'お問い合わせありがとうございました。\n'
+ 'このメールは自動返信メールです。\n'
+ '後ほど ' + userMail + ' 様あてにご連絡いたします。\n\n'
+ '-- お問い合わせ内容 ------------------------------------\n\n'
+ userMessage + '\n\n'
+ '----------------------------------------------------------------\n\n'
+ '--\n'
+ 'IMUZA.com\n'
+ 'http://www.imuza.com\n\n';
GmailApp.sendEmail(userMail, subject, body, {name: 'IMUZA.com'});
// 通知メール
subject = 'お問い合わせがありました';
body = 'お問い合わせがありました。\n'
+ userMail + ' あてに返信してください。\n\n'
+ '-- お問い合わせ内容 ------------------------------------\n\n'
+ userMessage + '\n\n'
+ '----------------------------------------------------------------\n\n'
+ '--\n'
+ 'IMUZA.com\n'
+ 'https://www.imuza.com\n\n';
GmailApp.sendEmail('通知を送りたいメールアドレス', subject, body, {name: 'IMUZA.com'});
}
}

もちろん、IMUZA.com などとなっているところは参考として残してあるだけですのでご自身のサイト名や URLにに変更してください。

結果と問題点

これでスパムの場合は確認メールや通知メールを送信しなくなります。ただし、Google Formには回答として保存されます。

その結果をみますと、やはりスパムの場合はトークンに何も入っていません。

問題としては、回答が保存されてしまうことと、ボットには関係ないことですが、「可能なら結果をクライアントに返す」ができなく、クライアント側でありがとうメッセージへ画面遷移してしまうことです。

とりあえずは成功ですが、この際もう少し Google Apps Script を調べてみようと思います。

詳解! GoogleAppsScript完全入門 ~GoogleApps & G Suiteの最新プログラミングガイド~

詳解! GoogleAppsScript完全入門 ~GoogleApps & G Suiteの最新プログラミングガイド~

  • 作者:高橋宣成
  • 出版社/メーカー: 秀和システム
  • 発売日: 2017/12/23
  • メディア: 単行本

AdSenseサイト運営者ポリシー違反レポート
はてなブログ用ボトムナビゲーション Bottom Navigation
Twitter
Facebook
ブックマーク
LINEで送る

最初のサイドバー

最新記事

2023/03/21

WordPress:メール送信にGmailのSMTPを使う(プラグインなし)

2023/03/10

WordPress:サムネイル付き次の記事/前の記事

2023/02/28

Twitterシェアリンクはintent/tweetを使おう

2023/02/21

GoogleタグマネージャーとアナリティクスGA4

2023/02/8

WordPress:人気記事を直近の期間指定で表示する

最新記事を一覧で見る

よく読まれている記事

よく読まれている記事を一覧で見る

カテゴリー

  • はてなブログ214
  • WebTips109
  • javascript98
  • Joomla!88
  • Windows68
  • Wordpress65
  • CSS63
  • Joomla!更新53
  • Linux49
  • はてなテーマ45
  • Google34
  • Plamo33
  • はてなプラグイン25
  • php22
  • Node.js18
  • Ubuntu16
  • SASS16
  • laravel415
  • Chrome11
  • cms-style10
  • iPhone9
  • ConoHa WING6
  • Git入門6
  • genesis6
  • Python5
  • Android5
  • PC全般4
  • Facebook4
  • スマートフォン4
  • 静的サイトジェネレーター3
  • Firefox3
  • SSD3
  • Blankslate3
  • Docker3
  • Twitter2
  • GitHub2
  • Mactype2
  • はてなブクマ1
  • 映画1
  • youtube1
  • rails入門1
  • Xserver1

Footer

My Web Sites

  • @半径とことこ60分
  • そんなには褒めないよ。映画評
  • IMUZA.com
  • GitHub

Related Sites

  • WordPress公式
  • WordPress関数リファレンス
  • PHPマニュアル

Contact Us

  • お問い合わせフォーム
  • Twitter
  • Facebook
  • Feedly

Copyright © 2023 · IMUZA.com