〖Python〗-- Tornado自定義session組件

【Tornado自定義session組件】

咱們在學習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 #有的話返回這個類
session_code.py
settings.py
 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()
app.py(應用)

遵循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>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>
index.html
相關文章
相關標籤/搜索