Google App Engine (Python) でセッションを使ってみる (PHPのsession_regenerate()も)
まずは、app/util.pyなんかに次のようなデコレーターを作っておく。
# -*- coding: utf-8 -*- import os import pickle import hashlib import Cookie import uuid from datetime import date, date, datetime, timedelta # Google App Engine imports. from google.appengine.ext.webapp import template, util from google.appengine.api import memcache def use_session(regenerate): def use_session_internal(func): def use_session_decorator(self): self.session_id = None self.session = None session_id = self.request.cookies.get('coiled-session', None) mc = memcache.Client() if session_id is not None: session = mc.get(session_id, 'session') if session is not None: self.session = session if regenerate: mc.delete(session_id, namespace="session") self.session_id = hashlib.sha1(str(uuid.uuid4())).hexdigest() else: self.session_id = session_id if self.session_id is None: self.session_id = hashlib.sha1(str(uuid.uuid4())).hexdigest() self.session = {} expires_date = datetime.utcnow() + timedelta(days=1) # expires_str = expires_date.strftime("%d %b %Y %H:%M:%S GMT") expires_str = expires_date.strftime("%a, %d %b %Y %H:%M:%S UTC") cookie = Cookie.SimpleCookie() cookie["coiled-session"] = self.session_id cookie["coiled-session"]["path"] = "/" cookie["coiled-session"]["expires"] = expires_str self.response.headers.add_header("Set-Cookie", cookie.output(header='')) func(self) if self.session_id is not None: if self.session is None: mc.delete(self.session_id, namespace="session") else: mc.set(self.session_id, self.session, time=60*60*24, namespace="session") return use_session_decorator return use_session_internal
このデコレーター使う側は、こんな風に書ける。
# -*- coding: utf-8 -*- from google.appengine.ext.webapp import WSGIApplication, RequestHandler from app.util import use_session class LoginPage(RequestHandler): @use_session(regenerate=False) def get(self): pass @use_session(regenerate=True) def post(self): pass
完全なサンプルにはなっていないが、なんとなく雰囲気だけ伝えたいところ。
ポイントとして、PHPのセッションはデフォルトではファイルに勝手に格納されるが、Google App Engineではファイルに書き込むことはできないので、memcachedを使っている。
また、デコレーターで引数を取れるようにするために、デコレーターの定義が三重の定義になっている。(defの中にdefの中にdefが入っている。)
アクセスするたびにセッションの保持期間が延長される実装になっている。
セッションIDは必ずアプリケーションで作成し、外部で作られた不正なセッションIDを受け入れないように気をつけている。(PHPで有名なセキュリティーホールありましたよね・・・。)