zoukankan      html  css  js  c++  java
  • tornado自定义session

    这开始之前我们先了解以下什么是cookiesession

    简单的说:

    • cookie是保存在客户端的键值对
    • session是保存在服务端的键值对
    • session依赖与cookie

    在Django中,可以直接操作cookie和session,在flask可以直接使用一个session对象和号称安全的cookie来实现session存储,而在tornado中只支持cookie,如果要实现session怎么办,我们只能自己美化轮子

    实现思路

       我们知道,在tornado中,多有的请求都是由RequestHandler对象来处理的。在RequestHandler源代码中,预留了一个钩子方法initialize,该方法会在实例化RequestHandler对象时执行。因此我们继承RequestHandler,并覆写initialize方法,这样我们就可以完成一定的自定义操作。

      此篇文章使用内存来实现session存储,存储在一个字典对象中,这里的字典对象,使用了jdb2模块中的对dict对象二次封装的功能,具体使用请参考:https://www.cnblogs.com/zhichaoma/p/9382937.html

      对于使用redis和其他非关系型数据库存储实现思路大致相同,只是session的存储位置不同

    实现代码

    目录结构,手动创建一个空的nosql.db文件

    session-demo/
    ├── base.py
    ├── main.py
    ├── nosql.db
    └── test.py
    

     main.py

    # -*- coding: utf-8 -*-
    #程序的入口
    import tornado.ioloop
    from tornado.httpserver import HTTPServer
    import tornado.web
    import test
    
    app = tornado.web.Application([
          (r'/t1/?', test.Test1),
          (r'/t2/?', test.Test2),
          (r'/t3/?', test.Test3),
          (r'/t4/?', test.Test4),
          ],
    	#加密cookie的密串
    	生成方式:
    	#import base64, uuid
        #base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes
        cookie_secret="bQd3T8WSORUGqEdnC6gUtuCp0jUYAm0OIrWJbjHe/zPA="
    )
    
    if __name__ == '__main__':
      httpserver = HTTPServer(app)
      httpserver.bind(port=8080)
      httpserver.start()
      tornado.ioloop.IOLoop.current().start()
    

     base.py

    # -*- coding: utf-8 -*-
    import tornado.web
    import time
    import jdb2
    
    # 初始化NoSQL DB
    noSql = jdb2.NoSql(dump=True, nosqlFile='nosql.db', dumpTime=3)
    session = noSql.createDB('session')
    
    
    class Session():
      #实现session的类
      def  __init__(self, handler):
        self.handler = handler   #连接对象
    	#两个cookie来匹配session
        self.random_index_str = self.handler.get_secure_cookie('_token_sson_', None)
        self.random_time_str = self.handler.get_secure_cookie('_tson_', None)
        self.random_str = '| m | z | c |'		#加密的随机字串
    	#如果只存在_token_sson_的cookie值,则删除内存中之前保存的键值对
        if self.random_index_str and not self.random_time_str:
          tmp = None
    	  #如果是bytes类型,转换为字符串
          if isinstance(self.random_index_str, bytes):
            tmp = self.random_index_str.decode()
          session.dropKey(tmp)
          self.random_index_str = None
    	#如果只存在_tson_的cookie值,则删除内存中之前保存的键值对
        elif self.random_time_str and not self.random_index_str:
          tmp = None
          if isinstance(self.random_time_str, bytes):
            tmp = self.random_time_str.decode()
          session.dropKey(tmp)
          self.random_time_str = None
    
      def __get_random_str(self):
        """
    	获取随机加密随机字符串
    	"""
        import hashlib, time
        md = hashlib.md5()
        md.update(bytes(str(time.time()) + self.random_str, encoding='utf-8'))
        return md.hexdigest()
    
      def __setitem__(self, key, value):
        """
    	设置值
    	"""
    	#如果两个cookie都不存在,生成加密随机字串
        if not self.random_index_str and not self.random_time_str:
          self.random_index_str = self.__get_random_str()
          self.random_time_str = self.random_index_str
        else:
          #如果两个cookie都不存在session存储的数据库中则生成随机加密字符串
          if isinstance(self.random_index_str, bytes):
            self.random_index_str = self.random_index_str.decode()
          if isinstance(self.random_time_str, bytes):
            self.random_time_str = self.random_time_str.decode()
          if self.random_index_str not in session.getKeys() and 
                  self.random_time_str not in session.getKeys():
            self.random_index_str = self.__get_random_str()
            self.random_time_str = self.random_index_str
    	#将bytes转换为str类型
        if isinstance(self.random_index_str, bytes):
          self.random_index_str = self.random_index_str.decode()
    	#在session库中创建指定加密串的对象,之后设置键值对
        session.createTable(self.random_index_str).setValue(key, value)
    	#设置_token_sson_ cookie 当关闭浏览器时cookie
        self.handler.set_secure_cookie("_token_sson_", self.random_index_str,expires_days=None)
        #设置_tson_ cookie 设置3小时后过期
        self.handler.set_secure_cookie('_tson_', self.random_index_str, expires=time.time() + 3*60**2)
        #设置一个cookie expires的优先级要高于expires_days
    
      def __getitem__(self, key):
        #将bytes转换为str类型
        if isinstance(self.random_index_str, bytes):
          self.random_index_str = self.random_index_str.decode()
        if isinstance(self.random_time_str, bytes):
          self.random_time_str = self.random_time_str.decode()
    	#如果两个cookie都不存的时候,直接返回None
        if not self.random_index_str and not self.random_time_str:
          return None
        else:
    	  #如果两个cookie相等时执行获取操作,否则之际返回None
          if self.random_index_str == self.random_time_str:
            current_user = session.getValue(self.random_index_str)
            if not current_user:
              return None
            else:
              return session.createTable(self.random_index_str).getValue(key)
          else:
            return None
    
      def __delitem__(self, key):
        """
        delete session
        :param key:
        :return:
        """
        random_index_str = None
        random_time_str = None
        if isinstance(self.random_index_str, bytes):
          random_index_str = self.random_index_str.decode()
        if isinstance(self.random_time_str, bytes):
          random_time_str = self.random_time_str.decode()
    	#如果传入的key为空或者None,则视为要删除当前session对象,
        if key == None or key == '':
          session.dropKey(random_index_str)
          session.dropKey(random_time_str)
          self.handler.clear_cookie("_token_sson_")
          self.handler.clear_cookie('_tson_')
        else:
    	  #如果键值对不为空,则删除当前session对象的指定key
          if random_index_str:
            session.createTable(random_index_str).dropKey(key)
          elif random_time_str:
            session.createTable(random_time_str).dropKey(key)
    
    
    class BaseHandlers(tornado.web.RequestHandler):
      #继承RequestHandler,并覆写部分功能
      def initialize(self):
        self.session = Session(self)
    

     test.py

    # -*- coding: utf-8 -*-
    from base import BaseHandlers
    
    class Test1(BaseHandlers):
      """
      获取当前session对象的指定key
      """
      def get(self):
        pass
      def post(self, *args, **kwargs):
        print('1', self.session['is_login'])
        return self.redirect('/t3')
    
    
    class Test2(BaseHandlers):
      """
      删除session的指定key
      """
      def get(self):
        del self.session['is_login']
        return self.redirect('/t3')
    class Test3(BaseHandlers):
      """
      设置session
      """
      def get(self, *args, **kwargs):
        self.write(
          """
          lt;form action="/t3" method="post"gt;
            key: lt;input type='text' name='name' /gt;
            lt;input type='submit' value='submit' /gt;
          lt;/formgt;
          lt;form action="/t2" method="get"gt;
             lt;input type='submit' value='claer' /gt;
          lt;/formgt;
           lt;form action="/t1" method="post"gt;
             lt;input type='submit' value='get' /gt;
          lt;/formgt;
          lt;/formgt;
           lt;form action="/t4" method="post"gt;
             lt;input type='submit' value='clear all ' /gt;
          lt;/formgt;
          """
        )
    
      def post(self, *args, **kwargs):
        if self.get_argument('name') == 'test':
          self.session['is_login'] = True
        return self.redirect('/t3')
    
    class Test4(BaseHandlers):
      """
      删除当前session对象
      """
      def get(self):
        pass
      def post(self, *args, **kwargs):
        del self.session['']
        return self.redirect('/t3') 

    调试过程中可以查看nosql.db文件,查看内存中session存储的变化

    关于tornado cookie时间设置问题可以参考

  • 相关阅读:
    linux中fork()函数详解
    并发和并行有什么区别?
    利用bochs调试Linux 0.11内核
    [调整] Firemonkey iOS 原生 Edit 透明框, 改变框色
    [修正] Firemonkey Windows 控件有虚线残影问题
    [示例] Firemonkey 图片按钮(3态)
    [示例] Firemonkey 不规则按钮实做
    [函数] Delphi FMX Windows 取得下载 Downloads 目录
    [工具] Firemonkey Style 调色工具(可另存 Style 文件)
    [教学] Delphi Berlin 10.1 开发 Windows 10 平板 App 远程调试
  • 原文地址:https://www.cnblogs.com/zhichaoma/p/9486502.html
Copyright © 2011-2022 走看看