LoginSignup
1
0

More than 5 years have passed since last update.

Google App Engine アプリで reCAPTCHA を利用する

Posted at

※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_code200 で decode_json_data['success']True だったらロボットではない、ということになります。

以上です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0