Tornado之Session实现
Tornado框架中,默认执行Handler的get/post等方法之前默认会执行 initialize方法,所以可以通过自定义的方式使得所有请求在处理前执行操作
import tornado.ioloop import tornado.web import time import hashlib # 将session_id保存在内存中 class Cache(object): def __init__(self): self.container = dict() def __contains__(self, item): return item in self.container def initial(self,random_str): self.container[random_str] = dict() def get(self,random_str,key): return self.container[random_str].get(key) def set(self,random_str,key,value): self.container[random_str][key] = value def delete(self,random_str,key): del self.container[random_str][key] def open(self): pass def close(self): pass def clear(self,random_str): del self.container[random_str] db = Cache # 这里的Cache可以换成任何其他想要的Session存储方式,这里为了演示方便就直接保存在内存中了 class Session(object): def __init__(self, handler): self.handler = handler self.random_str = None self.db = db() # 去用户请求信息中获取session_id,如果没有,表示是新用户 client_random_str = self.handler.get_cookie("session_id") if not client_random_str: # 新用户 self.random_str = self.create_random_str() self.db.initial(self.random_str) else: # 检查随机字符串是否在字典中,防止用户自己伪造session_id值 if client_random_str in self.db: # 老用户 self.random_str = client_random_str else: # 非法用户 重新为其赋值 self.random_str = self.create_random_str() self.db.initial(self.random_str) ctime = time.time() # 往客户端浏览器设置session_id self.handler.set_cookie("session_id", self.random_str, expires=ctime+1800) def create_random_str(self): value = str(time.time()) m = hashlib.md5() m.update(bytes(value, encoding="utf-8")) return m.hexdigest() def __setitem__(self, key, value): self.db.set(self.random_str, key, value) def __getitem__(self, key): return self.db.get(self.random_str, key) def __delitem__(self, key): self.db.delete(self.random_str, key) def clear(self): self.db.clear(self.random_str) class Foo(object): def initialize(self): self.session = Session(self) # 这里是一个重点,Foo作为HomeHandler的父类,因此这里的"self"就是HomeHandler的对象,所以可以调用"self.set_cookie()",把 super(Foo, self).initialize() # "self"传递给Session(),通过"handler"接收,这样就可以在Session()中调用"self.set_cookie()"了 class LoginHandler(Foo, tornado.web.RequestHandler): def get(self): self.session["user"] = "root" # 为了演示方便,这里就不去数据库查找用户名和密码了,直接赋值 self.redirect("/home") class HomeHandler(Foo, tornado.web.RequestHandler): def get(self): user = self.session["user"] if not user: self.redirect("https://www.biying.com") self.write("欢迎登陆:" + user) class MainHandler(Foo, tornado.web.RequestHandler): def get(self): # self.write("Hello, world") self.render("main.html") settings = { "template_path":"views", } application = tornado.web.Application([ (r"/index", MainHandler), (r"/login", LoginHandler), (r"/home", HomeHandler), ], **settings) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()