zoukankan      html  css  js  c++  java
  • 〖Python〗-- Tornado自定义session组件

    【Tornado自定义session组件】

    我们在学习Django框架的过程中,内部封装了session组件,以方便于我们使用进行验证。但是Tornado框架是没有session的,所以如果想使用session的话,就需要我们自己定制相对应的组件。在Tornado框架中是存在cookie机制的,所以我们可以利用加密的cookie以实现验证机制。通过配置文件决定数据信息存放的位置。是在缓存还是在内存中。具体代码如下:

    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文件夹下简单页面代码如下:

    <!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
  • 相关阅读:
    ArrayList用法
    MessageBox
    将文本文件导入Sql数据库
    在桌面和菜单中添加快捷方式
    泡沫排序
    Making use of localized variables in javascript.
    Remove double empty lines in Visual Studio 2012
    Using Operations Manager Connectors
    Clear SharePoint Designer cache
    Programmatically set navigation settings in SharePoint 2013
  • 原文地址:https://www.cnblogs.com/SHENGXIN/p/8076384.html
Copyright © 2011-2022 走看看