tornado session

tornado的session的简单实现,使用的是redis,其实一般情况,使用secure cookie不用session也行

session.py

# -*- coding: utf-8 -*-

from hashlib import sha1

import os, time

session_id = lambda: sha1('%s%s' % (os.urandom(16), time.time())).hexdigest()


class SessionHandler(object):
    _id = None
    _prefix = "_session:"
    _skip = ["_redis", "_request", "_id", "lastActive", "_prefix", "session_lifetime"]
    
    def __init__(self, request, redis, session_lifetime=60 * 60 * 24):
        self._request = request
        self._redis = redis
        self.session_lifetime = session_lifetime
        self.init_session()

    def init_session(self):
        """初始化"""
        _id = self._request.get_secure_cookie("session_id")
        if not _id:
            _id = session_id()
        else:
            if not self._redis.exists(_id):
                _id = session_id()
        self._request.set_secure_cookie("session_id", _id)
        self._id = _id

    def __getattr__(self, name):
        if name in self._skip:
            return object.__getattr__(self, name)
        else:
            return self._redis.hget(self._id, name)
        
    def __setattr__(self, name, value):
        if name in self._skip:
            object.__setattr__(self, name, value)
        else:
            self.init_session()
            self._redis.hset(self._id, name, value)
            self._redis.expire(self._id, self.session_lifetime)

    def __delattr__(self, name):
        if name in self._skip:
            object.__delattr__(self, name)
        else:
            return self._redis.hdel(self._id, name)

            
__all__ = ["SessionHandler", "session_id"]


test_session.py

# -*- coding: utf-8 -*-

from tornado.web import RequestHandler, Application
from tornado.ioloop import IOLoop
from session import SessionHandler
from redis import client
from tornado import escape

import tornado.web

class BaseHandler(RequestHandler):
    def initialize(self):
        redis = self.application.redis
        self.session = self.application.SessionHandler(self, redis, session_lifetime=20)
        self.current_password = self.session.password

    def get_current_user(self):
        return self.get_secure_cookie("username")


class MainHandler(BaseHandler):
    def get(self):
        if not self.current_user or not self.current_password:
            self.redirect("/login")
            return
        name = escape.xhtml_escape(self.current_user)
        self.write("Home Page | Logined | %s" % name)
        

class LoginHandler(BaseHandler):
    def get(self):
        if self.current_user and not self.current_password:
            html = """\
                <html>
                    <body>
                        <p>
                        session超时了,要重新输入密码!
                        </p>
                        <form action="/login" method="post">
                            Password:<input type="password" name="password">
                            <input type="submit" value="sign in">
                        </form>
                    </body>
                </html>
                """
        else:
            html = """\
                <html>
                    <body>
                        <p>
                        未登录,或者cookie超时了,要重新输入用户名和密码!
                        </p>
                        <form action="/login" method="post">
                            Username:<input type="text" name="username">
                            Password:<input type="password" name="password">
                            <input type="submit" value="sign in">
                        </form>
                    </body>
                </html>
                """
        self.write(html)
        
    def post(self):
        username = self.get_secure_cookie("username") or self.get_argument("username")
        password = self.get_argument("password")
        if not self.current_password:
            if username == "flyking" and password == "112358":
                self.set_secure_cookie("username", username)
                self.session.password = password
                self.redirect("/")
            else:
                raise tornado.web.HTTPError(403, "user or password error")
        else:
            self.redirect("/")
        
        
urls = [
        (r"/", MainHandler),
        (r"/login", LoginHandler),

    ]
    
settings = {
        "cookie_secret":"61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=", # 带签名的cookie
        "login_url":"/login",
        # "xsrf_cookies":"Ture", # 跨站伪造请求(Cross-site request forgery) 防范策略 xsrf_cookies
        
    }

app = Application(urls, **settings)
app.listen(8888)
app.redis = client.Redis()
app.SessionHandler = SessionHandler

IOLoop.instance().start()


你可能感兴趣的:(session,tornado)