reCAPTCHA form

reCAPTCHA v3 を Python CGI で使う

以前に reCAPTCHA v2 の導入記事を書きましたが、今回は reCAPTCHA v3 です。v2 の画像選択が手間になってきて、よりシンプルに扱える v3 に更新しようと思ったのがきっかけです。

チェックボックスにチェックする v2 と異なり、v3 はフォームに埋め込むものがありません。JavaScript で token を取得するところまでは一緒なのですが、その token を自分でフォームに埋め込む必要があります。

reCAPTCHA への登録の仕方は v2 も v3 も同じなので、前回の記事に譲ります。

クライアントサイド

head 要素内に次のコードを埋め込みます。

<script src="https://www.google.com/recaptcha/api.js?render=SITE_KEY"></script>

SITE_KEY の部分は各々発行されたものに置換えてください。

次に、どこでも良いので次のコードを埋め込みます。head 要素内でも良いですし、body の最後でも問題ありません。

<script>
grecaptcha.ready(function() {
  grecaptcha.execute('SITE_KEY', {action: 'action_name'})
  .then(function(token) {
    document.getElementById('g-recaptcha-response').value = token;
  });
});
</script>

'action_name' は名前分けしておくと、admin console で分析が行えるようです。

最後に、フォーム要素の中に次の隠し要素を埋め込んでおきます。

<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response" value="">

先ほどの JavaScript が実行されると、token がこの要素の value に入ります。

サーバーサイド (Python2)

今回はお手軽さで cgi.FieldStorage() と urllib を使います。

import cgi
import urllib, urllib2
import json

# フォームの取得
form = cgi.FieldStorage()

# g-recaptcha-responseの値を取得
response = form.getfirst('g-recaptcha-response', '')

# APIに照合を行う
params = urllib.urlencode({'secret': SECRECT_KEY, 'response': response})
req = urllib2.Request('https://www.google.com/recaptcha/api/siteverify', params)
result = json.loads(urllib2.urlopen(req).read())

返ってくる json には次の値が含まれています。

{u'action': u'action_name', u'score': 0.9, u'hostname': u'kuratsuki.net', u'challenge_ts': u'2018-12-06T06:51:20Z', u'success': True}
success
True|False 正しい token が送られたかどうかの判定
score
0.0-1.0 bot(0.0) に近いか人間(1.0)に近いかを数値で表します
action
string action 名
challenge_ts
yyyy-MM-dd'T'HH:mm:ssZZ タイムスタンプ
hostname
string reCAPTCHA が行われたホスト名
error-codes
[] エラーがあったときのエラーのリスト

サーバーサイドではこの score を用いて処理を分岐させれば良いようです。

参考