FC2ブログ

スポンサーサイト

-------- --:--:-- --

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【Python】【Google App Engine】リクエストの共通処理とセッション管理

2011-04-13 20:46:16 Wed

2011年4月12日

セッションを自前で用意しようと思うとかなり難しい。

セッションはここでは、HTTPアクセスされたときにクライアントを識別するための方法とでも考えておきます。

自前は本当はよくないんですが、GAEにはセッション機能はないためやむを得ず実装するなら、という前置きの上でメモ。

下記を参考にさせて頂きました。
ログインログアウト
http://hujimi.seesaa.net/article/155264201.html
リクエスト共通処理の実装方法
http://d.hatena.ne.jp/kaorumori/20110114/1295101373

■ユーザとセッションのエンティティ

class User(db.Model):
    id = db.StringProperty()
    password = db.StringProperty()
    
class Session(db.Model):
    user = db.ReferenceProperty(User)
    id = db.StringProperty(required = True)
    ip = db.StringProperty()


■リクエストの共通処理(ここではセッション情報を確認し、ログイン状態を判定)

class BaseHandler(webapp.RequestHandler):
    
    def __init__(self):
        self.loginflg = False

    def render(self):
    	#クッキーからsessionidの値を取得する
        id = self.request.cookies.get("sessionid","")
    	#今は使わないが、携帯電話はcookieを持てないので、URLリクエストにsessionidを追加することを考慮しておく
        if id == '' or id is None:
            id = self.request.get("sessionid")
        if id:
    		#IPアドレスと保存されていたcookieをチェックし、ログイン時に発行されたセッションであるかどうか判定する
            session = Session.all().filter("ip", self.request.remote_addr).filter("id",id).fetch(1).pop()
            if session:
                self.loginflg = True
        else :
    		#認証エラーの場合、ログイン画面を表示する
            self.response.out.write(
                """
                <html>
                    <head></head>
                        <body>
                            Login User</br>
                            <form method='post' action='/login'>
                                <input type='text' name='id'></input></br>
                                <input type='password' name='password'></input></br>
                                <input type='submit' value='submit'></input></br>
                            </form>
                            <a href='/register'>Register user</a>
                        </body>
                </html>
                """)




■あるリクエストをうけたときの1つのCGI。

class HomeHandler(BaseHandler):

    #コンストラクタ
    def __init__(self):
    	#親クラスのコンストラクタを呼び出す。これがないと子クラスが親クラスのコンストラクタをオーバーライドしてしまい、親クラスのコンストラクタが実行されない
        BaseHandler.__init__(self)
    
    def get(self):
    	#ログイン共通処理を呼び出す。本来ならフィルタなどでやりたいところだができないため、コーディングルールとしてこういう記述を入れる
        self.render()
        if not self.loginflg:
            return
		#適当に処理…



■ログイン処理。

class LoginHandler(webapp.RequestHandler):
	#パスワードはmd5でダイジェストし、Base64でエンコードする
    def post(self):
        users = User.all().filter("id",self.request.get("id")).filter("password", base64.b64encode(hashlib.md5(self.request.get("password")).hexdigest()))
        
        for user in users:
    		#ログイン成功したとき、uuidでアプリで唯一らしき意味のないランダムな文字列を生成し、これをセッションIDとする。なお、HTTPのアクセス元IPアドレスとセットにする
            session = Session(id = str(uuid.uuid4()), user=user, ip=self.request.remote_addr)
            session.put()
	    	#HTTPヘッダにクッキー情報を追加する。セッションIDと有効期限、有効なパスを設定する
            self.response.headers.add_header(
                "Set-Cookie",
                "sessionid=%s; expires=Fri, 31-Dec-2020 23:59:59 GMT; path=/" % session.id
            )
        
        self.redirect("/")


■ログアウト処理

class LogoutHandler(BaseHandler):
    def get(self):

        self.render()
        if not self.loginflg:
            return

        id = self.request.cookies.get("sessionid","")
        sessions = Session.all().filter("id",id)
        
        for session in sessions:
            db.delete(session)
        
    	#クッキーの有効期限を過去日にして、クッキーを無効にする
        self.response.headers.add_header(
            "Set-Cookie",
            "sessionid=hoge; expires=Fri, 31-Dec-1999 23:59:59 GMT; path=/"
        )
        
        self.redirect("/")


■ユーザ登録処理

class UserRegisterHandler(webapp.RequestHandler):
    def get(self):
            self.response.out.write(
                """
                <html>
                    <head></head>
                        <body>
                            Register User</br>
                            <form method='post' action='/register'>
                                <input type='text' name='id'></input></br>
                                <input type='password' name='password'></input></br>
                                <input type='submit' value='submit'></input></br>
                            </form>
                            <a href='/'>back</a>
                        </body>
                </html>
                """)
    
    def post(self):
        id = self.request.get("id")
        temp_ps = self.request.get("password")
        flg = False
        if id == '' or id == None:
            flg = True
        if User.all().filter("id", id).count(1000) >= 1:
            flg = True
        if temp_ps == '' or temp_ps == None:
            flg = True
        if flg:
            self.redirect("/register")
            return
        
        user = User()
        user.id = id
        user.password = base64.b64encode(hashlib.md5(self.request.get("password")).hexdigest())
        user.put()
        self.response.out.write(
                                """<html><head></head><body>success</br><a href='/'>login</a></body></html>""")

スポンサーサイト

⇒comment

Secret

名言集
全記事(数)表示
全タイトルを表示
ブログ内検索
Loading
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。