GAEでOAuthというかTwitter認証してみた。


結構てこずりましたが、Google App Engine for Pythonで
OAuth認証というかTwitter認証をしてみました。

Softbankの夏モデル携帯でTwitterが機能の一つとして入っているものが発表され、
これからTwitterの人口はどんどん増えるはずなので、
OpenIDみたいな統合認証のようにOAuthを使えたらなぁという思いでコーディングしてみました。

元ネタはサンプルコードで分かるGAE&Twitter API開発。 その節はお世話になりました。

oauth.py, simple_cookie.pyなどは上記のリンク先から取得してください。

verify後にリロードするとバグっていたので、self.redirect('/')で直しました。

#!/usr/bin/env python
# -*- coding:utf-8 -*-

__author__ = "Hironori Watanabe"

import time
import datetime
import logging

import os
import oauth
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template
from simple_cookie import Cookies
from google.appengine.ext import db

_DEBUG = True
INDEX_TEMPLATE_NAME = 'index.html'
LOGIN_TEMPLATE_NAME = 'login.html'
HOME_TEMPLATE_NAME = 'home.html'

# twitterのconsumer_keyとconsumer_secret_keyを指定
CONSUMER_KEY = "xxxxx自分のコンシューマキーを入れてねxxxxx"
CONSUMER_SECRET_KEY = "xxxx自分のシークレットキーを入れてねxxxxx"
# cookieの有効時間(秒)お好きにどうぞ。
COOKIE_EXPIRE_TIME = 300

class Testmodel(db.Model):
  id = db.StringProperty(required=True)
  username = db.StringProperty()

class BaseRequestHandler(webapp.RequestHandler):
  """
  Common template generation function.

  When you call generate(), we augment the template variables supplied with the current user in the 'user' variable and the current webapp request in the 'request' variable.
  """
  def generate(self, template_name, template_values={}):
    values = {
      'request': self.request,
      'application_name': 'Appname',
    }
    values.update(template_values)
    directory = os.path.dirname(__file__)
    path = os.path.join(directory, os.path.join('templates', template_name))
    self.response.out.write(template.render(path, values, debug=_DEBUG))


class MainHandler(BaseRequestHandler):
  def get(self, mode=""):
    """ TwitterClient, cookieクラスの作成"""
    (client, cookie) = createClientAndCookie(self)

    if mode == "login":
      self.redirect(client.get_authorization_url())
      return

    if mode == "logout":
      ClearCookie(self, cookie)
      self.generate(INDEX_TEMPLATE_NAME, {})
      return

    """ Twitterの認証後 """
    if mode == "verify":
      VerifyAuth(self, client, cookie)
      query = Testmodel.all()
      query.filter("id =", cookie["user_token"])
      tests = query.fetch(1)

      if not tests:
        test = Testmodel(id=cookie["user_token"])
        test.username = cookie["screen_name"]
        test.put()
        self.generate(HOME_TEMPLATE_NAME, {'username':test.username})
        self.redirect('/')
        return
      else:
        for test in tests:
          username = test.username
        self.generate(HOME_TEMPLATE_NAME, {'username':username})
        self.redirect('/')
        return

    """ 通常(認証チェック) """
    if checkUserInfo(self):
      tests_query = Testmodel.all()
      tests_query.filter("id =", cookie["user_token"])
      tests = tests_query.fetch(1)
      for test in tests:
        username = test.username
      self.generate(HOME_TEMPLATE_NAME, {'username':username})
      return
    else:
      self.generate(LOGIN_TEMPLATE_NAME, {})
      return

  def post(self, mode=""):
    pass


"""
共通処理

Twitter APIを利用するTwitterClientクラス(oauth.py)と
ユーザー情報を保存するCookiesクラス(simple_cookie.py)を作成する
"""
def createClientAndCookie(self):
  callback_url = "%s/verify" % self.request.host_url
  client = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET_KEY, callback_url)

  """Cookiesクラスの作成"""
  cookie = Cookies(self, max_age=COOKIE_EXPIRE_TIME)
  return client, cookie

def checkUserInfo(self):
  cookie = Cookies(self, max_age=COOKIE_EXPIRE_TIME)

  if cookie.has_key("user_token") and cookie.has_key("user_secret") and cookie.has_key("screen_name"):
    return True
  else:
    return False

def VerifyAuth(self, client, cookie):
  auth_token = self.request.get("oauth_token")
  auth_verifier = self.request.get("oauth_verifier")
  user_info = client.get_user_info(auth_token, auth_verifier=auth_verifier)
  cookie["user_token"] = user_info["token"]
  cookie["user_secret"] = user_info["secret"]
  cookie["screen_name"] = user_info["username"]

def main():
  application = webapp.WSGIApplication([
    ('/(.*)', MainHandler)], 
    debug = _DEBUG)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()

コメント

このブログの人気の投稿

perlのMIME::Liteならメール送信はすぐ書ける。その2

Pray For Japanのまとめページつくりました。