咱們在學習Django框架的過程當中,內部封裝了session組件,以方便於咱們使用進行驗證。可是Tornado框架是沒有session的,因此若是想使用session的話,就須要咱們本身定製相對應的組件。在Tornado框架中是存在cookie機制的,因此咱們能夠利用加密的cookie以實現驗證機制。經過配置文件決定數據信息存放的位置。是在緩存仍是在內存中。具體代碼以下:html
import time import json import redis import hashlib import importlib import settings def gen_random_str(): """ 獲取隨機字符串,做爲session的key """ md5 = hashlib.md5() md5.update(str(time.time()).encode("utf-8")) return md5.hexdigest() class CacheSession(object): """ 內存中獲取 """ container = {} # 保證類實例化一次,僅有一個session,同一個對象也是一個session def __init__(self,handler): self.handler = handler #接收handler對象 self.session_id = settings.SESSION_ID #從配置文件中獲取session的id self.expires = settings.EXPIRERS #從配置文件中獲取session的超時時間 self.initial() #初始化 def initial(self): #先從cookies獲取隨機字符串,能拿到而且在container中證實以前訪問過,session 不變,如果不知足就從新生成 client_random_str = self.handler.get_cookie(self.session_id) #從cookies中獲取session_id if client_random_str and client_random_str in self.container: #判斷 self.random_str = client_random_str #存在就賦值 else:#不存在就建立,或是錯誤 self.random_str = gen_random_str() #生成一個新的隨機字符串 self.container[self.random_str] = {} #每次請求來,在超時時間以內,都須要回寫一次,以延長超時時間 expires = time.time()+self.expires self.handler.set_cookie(self.session_id,self.random_str,expires=expires) def __getitem__(self, item): return self.container[self.random_str].get(item) def __setitem__(self, key, value): self.container[self.random_str][key]=value def __delitem__(self, key): if key in self.container[self.random_str]: del self.container[self.random_str][key] class RedisSession(object): """ 緩存中獲取 """ def __init__(self,handler): self.handler = handler self.session_id = settings.SESSION_ID self.expires = settings.EXPIRERS self.initial() @property def conn(self): """ 鏈接redis :return: """ conn = redis.Redis(host=settings.RedisHost,port=settings.RedisPort) return conn def initial(self): """ 初始化 :return: """ client_random_str = self.handler.get_cookie(self.session_id) if client_random_str and self.conn.exists(client_random_str): #檢測隨機字符串及redis中的隨機字符串是否存在 self.random_str = client_random_str else: self.random_str = gen_random_str() expires = time.time()+self.expires self.handler.set_cookie(self.session_id,self.random_str,expires=expires) self.conn.expire(self.random_str,self.expires) #設置緩存數據額度超時時間 def __getitem__(self, item): #注意在redis中獲取的數據全是字節類型,須要轉成字符串再json反序列化 data_str = self.conn.hget(self.random_str,item).decode("utf-8") data_dict = json.loads(data_str) if data_str else None return data_dict def __setitem__(self, key, value): self.conn.hset(self.random_str,key,json.dumps(value)) def __delitem__(self, key): self.conn.hdel(self.random_str,key) class SessionFactory(object): """ 工廠模式,經過導入的配置文件,實例化對應方法的 """ @staticmethod def get_session(): engine = settings.SESSION_ENGINE module_path,cls_name = engine.rsplit('.',maxsplit=1) md = importlib.import_module(module_path) #以字符串的形式導入 cls = getattr(md,cls_name) #反射驗證,獲取有沒有這個方法 return cls #有的話返回這個類
1 import tornado.ioloop 2 import tornado.web 3 from tornado.web import RequestHandler 4 from session_code import SessionFactory #導入自定義session文件的工廠方法 5 6 #建立能夠調用session方法的類,讓其餘須要使用的類去繼承 7 class SessionHandler(object): 8 9 def initialize(self,*args,**kwargs): 10 """ 11 重寫實例化中的鉤子函數,用於自定義實現某些方法 12 :param args: 13 :param kwargs: 14 :return: 15 """ 16 cls = SessionFactory.get_session() #獲取使用的類方法 17 self.session = cls(self) #構造方法,把當前的請求類(handler)的對象(self)做爲參數傳遞給session__code進行構造session。 18 19 class LoginHandler(SessionHandler,RequestHandler): 20 21 def get(self, *args, **kwargs): 22 self.render("login.html") 23 24 def post(self, *args, **kwargs): 25 26 user = self.get_argument("user") 27 pwd = self.get_argument("pwd") 28 29 # 簡單實現用戶登陸認證,能夠從數據庫中獲取數據 30 if user=="aaa" and pwd == "123": 31 # 驗證,在跳轉以前,把信息寫入session中 32 self.session["user"]=user # 寫入session 33 self.redirect("/index") # 跳轉到index頁面 34 else: 35 self.render("login.html") # 不然的話,就跳轉到登陸頁面 36 37 class IndexHandler(SessionHandler,RequestHandler): 38 39 def get(self, *args, **kwargs): 40 user = self.session["user"] # 從session中獲取信息 41 if user: 42 self.write("歡迎登陸") 43 else: 44 self.redirect("/login") 45 46 set = { 47 "template_path":"views", 48 } 49 50 application = tornado.web.Application([ 51 (r"/login",LoginHandler), 52 (r"/index",IndexHandler), 53 ],**set) 54 55 if __name__ == '__main__': 56 application.listen(8888) 57 tornado.ioloop.IOLoop.instance().start()
遵循MVC模式使用Tornado框架,建立用於存儲頁面的views文件夾。在app.py文件應用中,設置對於的配置信息。views文件夾下簡單頁面代碼以下:web
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1 class="c1">登陸</h1> <form method="POST"> <input type="text" name="user"> <input type="text" name="pwd"> <input type="submit" value="提交"> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> </body> </html>