※2016年6月30日に書いたブログ記事からの転記です。
1. reCAPTCHA にサイトを登録して site-key と secret-key を取得
まず、reCAPTCHAのサイトで site-key と secret-key を取得します。
「Register a new site」というフォームがあるので、「Label」と「Domains」の欄を記入して「Register」をクリックします。
導入手順が表示され、site-key および secret-key が取得できます。
- site-key は reCAPTCHA ウィジェットを reCAPTHCA API から取得する際に送信されるトークン
- secret-key はサーバーサイドプログラムから reCAPTCHA の API に送信するトークン
この2つは、app.yaml
に環境変数として記述しておきます。
env_variables:
# reCAPTCHA
RECAPTCHA_SITE_KEY: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
RECAPTCHA_SECRET_KEY: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
2. クライアントサイド(HTML)の実装
さて、では表示された導入手順にしたがって、まずはクライアントサイドの実装です。フォームに reCAPTCHA ウィジェットが表示されるようにHTMLを編集します。
<html>
<head>
<script src='https://www.google.com/recaptcha/api.js'></script>
</head>
<body>
<form method="post" action="">
<label>コメント:<input type="text" name="comment" value=""></label>
<div class="g-recaptcha" data-sitekey="{{ env.RECAPTCHA_SITE_KEY }}"></div>
</form>
</body>
</html>
こうすると、フォームに reCAPTCHA ウィジェットが表示されるようになります。
3.サーバーサイドの実装(Python での例)
次に、サーバーサイドの実装です。フォームから送信された値を受け取るリクエストハンドラーを作成します。
import json
import urllib
from google.appengine.api import urlfetch
from google.appengine.ext import ndb
import jinja2
import webapp2
class Comment(ndb.Model)
created_at = ndb.DateTimeProperty(auto_now_add=True)
body = ndb.TextProperty()
class CommentsHandler(webapp2.RequestHandler):
def render(self, form_values={}, form_errors={}):
query = Comment.query()
query = query.order(-Comment.created_at)
comments = query.fetch(25)
template_values = {
'form_values': form_values,
'form_errors': form_errors,
'comments': comments,
'env': os.environ,
}
template = JINJA_ENVIRONMENT.get_template('comments.html')
self.response.write(template.render(template_values))
def get(self):
self.render()
def post(self):
form_values = {}
form_errors = {}
form_values['comment'] = self.request.get('comment')
if form_values['comment'] == '':
form_errors['comment'] = u'コメント本文を入力してください'
# reCAPTCHA認証
recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify'
form_fields = {
'secret': os.environ['RECAPTCHA_SECRET_KEY'], # app.yaml に記述した環境変数から取得
'response': self.request.get('g-recaptcha-response'),
'remoteip': self.request.remote_addr,
}
form_data = urllib.urlencode(form_fields)
response = urlfetch.fetch(
url=recaptcha_url,
payload=form_data,
method=urlfetch.POST,
)
if response.status_code == 200:
json_data = response.content
decode_json_data = json.loads(json_data)
if not decode_json_data['success']:
form_errors['captcha'] = u'スパム判定をクリアしてください'
else:
self.abort(500)
if len(form_errors) > 0:
self.render(
form_values=form_values,
form_errors=form_errors,
)
else:
comment_key = Comment(
body=form_values['comment'],
).put()
self.redirect('/comments/%s' % comment_key.urlsafe()) # 適当なURLにリダイレクト
POST で送信されてくる reCAPTCHA ウィジェットの判定結果と secret-key、および IPアドレスを reCAPTHCA の API に渡してあげると、reCAPTCHA のサーバーが判定結果を JSON 形式で返してきます。
あとはその JSON をパースして status_code
が 200
で decode_json_data['success']
が True
だったらロボットではない、ということになります。
以上です。