这开始之前我们先了解以下什么是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时间设置问题可以参考

tornado自定义session的更多相关文章

  1. Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架

    Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloop import tornado.web from myhas ...

  2. tornado 自定义session (二)

    有了上一步的基础,我们将session改造成一个模块,这样我们就可以通过配置,来使用不同方式(redis,数据库等)的session. 添加一个新目录:TornadoSession conf.py是配 ...

  3. tornado 自定义session (一)

    tornado 中没有session功能,需要我们自己实现. 目录: settings: settings = { 'template_path': 'templates', 'static': 's ...

  4. Tornado 自定义Form,session实现方法

    一. 自定义Tornado 验证模块 我们知道,平时在登陆某个网站或软件时,网站对于你输入的内容是有要求的,并且会对你输入的错误内容有提示,对于Django这种大而全的web框架,是提供了form表单 ...

  5. Python web框架 Tornado(三)自定义session组件

    我们在学习Django框架的过程中,内部封装了session组件,以方便于我们使用进行验证.但是Tornado框架是没有session的,所以如果想使用session的话,就需要我们自己定制相对应的组 ...

  6. python_way ,自定义session

    python_way ,自定义session container = {} #可以是数据库,可以是缓存也可以是文件 class Session: def __init__(self, handler) ...

  7. Tronado自定义Session

    这里就不一一诉说Session和Cookie直接的关系了,下面以一张图来概括: 下面是一个简单的Tornaod自定义Session的例子,看完后你可能会明白为什么我们在Django里可以直接使用req ...

  8. 第二百六十九节,Tornado框架-Session登录判断

    Tornado框架-Session登录判断 Session需要结合cookie来实现 Session的理解 1.用户登录系统时,服务器端获取系统当前时间,进行nd5加密,得到加密后的密串 2.将密串作 ...

  9. 可灵活扩展的自定义Session状态存储驱动

    Session是互联网应用中非常重要的玩意儿,对于超过单台部署的站点集群,都会存在会话共享的需求.在web.config中,微软提供了sessionstate节点来定义不同的Session状态存储方式 ...

随机推荐

  1. Selenium自动化-调用Mysql数据库

    上几篇博客发布了几篇Selenium入门知识和进阶, 现在附上如何 从数据库中取值 能够逐行取值,并且返回二维数组 import java.io.FileInputStream; import jav ...

  2. Dynamics 365使用Execute Multiple Request删除系统作业实体记录

    摘要: 本人微信公众号:微软动态CRM专家罗勇 ,回复295或者20190112可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me ...

  3. centos7 安装java运行环境

    1.检测是否存在相关历史版本 shell:java-version 1.1.存在相关OpenJDK和其他版本SDK则需要删除,如图. 查看详细信息,命令窗口输入,shell:rpm -qa | gre ...

  4. 统计 flv视频总时长

    在学习孟媛的视频课程.网上能下载的是flv格式.那我在学习之前,我要统计一下这个课程的数量,他会用多长时间,这样方便我在学习过程中不断的回顾,进行时间管理.我大概就可以统计出来这个视频多长时间可以学完 ...

  5. 基于DataTables实现根据每个用户动态显示隐藏列,可排序

      前言 在后台管理系统开发中,难免会出现列数太多的情况,这里提供一个解决方案:用户设置显示哪些列,每个用户互不影响,并且可以根据用户的习惯设置列的排序. 1.演示 2.html代码说明 3.java ...

  6. 解决ajax get post方式提交中文参数乱码问题

    最近在工作中遇到,使用ajax get方式提交中文参数的时候出现乱码,通过上网搜索,总结出比较简单的两种解决方案: 第一种,由于tomcat默认的字符集是ISO-8859-1,修改Tomcat中的se ...

  7. Myeclipse、eclipse安装lombok

    Lombok简介 Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法.官方地址:https:/ ...

  8. 解析Object.defineProperty的作用

    对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值. 定义对象可以使用构造函数或字面量的形式: 除了以上添加属性的方式,还可以使用Object.defineProperty定义新属性 ...

  9. MySQL之ORM框架SQLAlchemy

    一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取 ...

  10. spring boot拦截器WebMvcConfigurerAdapter,以及高版本的替换方案(转)

    文章转自 http://blog.51cto.com/12066352/2093750 最近项目采用spring icloud,用的spring boot版本是1.5.x的,spring boot 2 ...