前編 に引き続いて、Google OpenID API を使ったサンプルについて書いていきます。
「OpenID認証(ID入力)」モジュール
前回記事でも触れたが、OpenID認証(ID入力) はID入力を必要とするプロバイダ向けのモジュールである。
入力したIDを create_login_url関数にパラメーターとして渡し、URLを生成しリダイレクトする動作となる。
まずID入力画面だが、OpenID Foundation の画面を真似てみた(下イメージ)。
参考: OpenID Foundation - How do I log in with OpenID?
今回のモジュールの画面(下イメージ)。
それでは OpenID認証(ID入力) モジュールのテンプレートを次に示してみる。
-
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>openid login</title> <link rel="stylesheet" type="text/css" href="/css/openid.css"> </head> <body> <form method="post" action="{% url InputOpenidHandler %}"> <table class="openid" hspace=30px vspace=30px height=100px width=500px > <tr align="left"><th width=10px></th><th>{{ title }}</th><th width=10px></th></tr> <tr align="left"><td></td><td valign="bottom">{{ text }}</td><td></td></tr> <tr><td></td> <td valign="top"> <input type="hidden" name="cont" value="{{ cont|escape }}"> <input type="hidden" name="provider" value="{{ provider|escape }}"> <input type="text" size="30" id="openid_url" name="openid_url" class="openid" value="{{ def_url }}"/> <input type="submit" id="openid_url_submit" name="openid_url_submit" class="openid" value="Sign in"/> </td><td></td> </tr> <tr><td></td><td class="error">{{ error }}</td><td></td></tr> </table> </form> </body> </html>
- ソース3 解説
- OpenID は URL だが、そのまま項目だけ用意しても入力へのハードルが高い。このためプロバイダー毎のガイダンスを用意した。
ガイダンスは、入力項目上のメッセージ(11・12行目) 及び 入力項目中の URL文字列(16・17行目)だ。 - Sign in ボタンを押すと Post関数が呼び出される(9行目)。
- OpenID は URL だが、そのまま項目だけ用意しても入力へのハードルが高い。このためプロバイダー毎のガイダンスを用意した。
テンプレート用CSSソースも示す。
-
.openid { font-family: 'Helvetica' sans-serif; font-size:100%; behavior: url(/css/PIE.htc); } .error { padding: 0px 0px 0px 25px; color: red; font-weight: bolder; } table.openid { background-color: #ccccff; border-radius: 5px; behavior: url(/css/PIE.htc); } input#openid_url { padding: 2px 5px 2px 25px; border-style: solid; border-width: 1px; background-image: url(/images/openid-icon.gif); background-repeat: no-repeat; background-position: left center; background-size:contain; behavior: url(/css/PIE.htc); } input#openid_url_submit { padding: 2px 8px; }
次に、OpenID認証(ID入力) のプログラムである。
-
# -*- coding: utf-8 -*- import os import urllib2 from google.appengine.api import users from google.appengine.ext.webapp import template from base_handler import BaseHandler class InputOpenidHandler(BaseHandler): def set_message_parameter(self, provider, **kwargs): prov_msg = {u'hatena':{'def_url':u'http://www.hatena.ne.jp/','title':u'はてなでログイン','text':u'はてな OpenID は、 <u>http://www.hatena.ne.jp/はてなID/</u> です。'}, u'defalut':{'def_url':u'http://','title':u'OpenID ログイン','text':u'あなたの OpenID を入力してください'}} if provider not in prov_msg: provider = u'defalut' for k, v in prov_msg[provider].iteritems(): kwargs.update({k:v}) return kwargs def get(self): provider = self.request.get('provider') template_values = self.set_message_parameter(provider) template_values = self.make_parameter_dict('cont', 'error', 'provider', **template_values) path = os.path.join(os.path.dirname(__file__), 'templates', 'input_openid.html') self.response.out.write(template.render(path, template_values)) def post(self): cont = self.request.get('cont') openid_url = self.request.get('openid_url') try: if not openid_url: raise urllib2.URLError login_url = users.create_login_url(dest_url = cont, federated_identity = openid_url) urllib2.urlopen(urllib2.Request(login_url)) self.redirect(login_url) except: url = self.make_url(**self.make_parameter_dict('cont','provider', error = 'OpenID url error')) self.redirect(url)
- ソース5 解説
- select_login.html から provider 変数を受け取る(20行目)。
- Get関数で画面を呼び出すが、その時 set_message_parameter 関数でプロバイダー毎のメッセージをセットする(21行目)。
- Post関数内で、create_login_url を使って URL を生成する(32行目)。
- 生成した URL を urlib2.urlopen を使って妥当性をチェックする(33行目)。
- URL へリダイレクトする(34行目)。
前回の記事でも触れた、Get/Postでの変数受け渡し用の関数を定義している BaseHandler クラスについても触れておく。
「BaseHandler」モジュール
このモジュールは認証とは関係無い。セッションを使っていないため、関数(画面)間で変数を受け渡すために使用している。
-
# -*- coding: utf-8 -*- from google.appengine.ext import webapp class BaseHandler(webapp.RequestHandler): def make_parameter_dict(self, *args, **kwargs): ''' make parameter for post method ''' for arg in args: kwargs.update({arg: self.request.get(arg)}) return kwargs def make_url(self, **kwargs): ''' make url string ( parameter for get method ) ''' param = '' for k, v in kwargs.iteritems(): if v is not None: param += ('?%s=%s' % (k,v)) if param == '' else ('&%s=%s' % (k,v)) return self.request.url + param
- ソース6 解説
- BaseHandler クラスは webapp.RequestHandler クラスを継承している(4行目)。
- make_parameter_dict は、変数名と値を渡すと辞書形で変数を返す(5行目)。
- make_url は、現在の URL を返す(11行目)。辞書型変数を渡した場合、Get関数用の変数付き URL を返す。
前回の記事と今回で、認証関係のモジュールについて触れた。次回の記事では、アプリケーションへの組み込みについて書いていきたい。