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

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
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

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
#配置文件 # session 存储类型 # 存储在内存中
SESSION_ENGINE = "session_code.CacheSession" # 存储在redis缓存中
# SESSION_ENGINE = "session_code.RedisSession"
# RedisHost = ""
# RedisPort = 6379 SESSION_ID = "__session__id__"
EXPIRERS = 300

settings.py

#!/usr/bin/env python
# _*_ coding:utf-8 _*_ import tornado.ioloop
import tornado.web
from tornado.web import RequestHandler
from session_code import SessionFactory #导入自定义session文件的工厂方法 #创建可以调用session方法的类,让其他需要使用的类去继承
class SessionHandler(object): def initialize(self,*args,**kwargs):
"""
重写实例化中的钩子函数,用于自定义实现某些方法
:param args:
:param kwargs:
:return:
"""
cls = SessionFactory.get_session() #获取使用的类方法
self.session = cls(self) #构造方法,把当前的请求类(handler)的对象(self)作为参数传递给session__code进行构造session。 class LoginHandler(SessionHandler,RequestHandler): def get(self, *args, **kwargs):
self.render("login.html") def post(self, *args, **kwargs): user = self.get_argument("user")
pwd = self.get_argument("pwd") # 简单实现用户登录认证,可以从数据库中获取数据
if user=="aaa" and pwd == "":
# 验证,在跳转之前,把信息写入session中
self.session["user"]=user # 写入session
self.redirect("/index") # 跳转到index页面
else:
self.render("login.html") # 否则的话,就跳转到登录页面 class IndexHandler(SessionHandler,RequestHandler): def get(self, *args, **kwargs):
user = self.session["user"] # 从session中获取信息
if user:
self.write("欢迎登录")
else:
self.redirect("/login") set = {
"template_path":"views",
} application = tornado.web.Application([
(r"/login",LoginHandler),
(r"/index",IndexHandler),
],**set) if __name__ == '__main__':
application.listen(8888)
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

Python web框架 Tornado(三)自定义session组件的更多相关文章

  1. Python Web框架 tornado 异步原理

    Python Web框架 tornado 异步原理 参考:http://www.jb51.net/article/64747.htm 待整理

  2. Python web框架 Tornado异步非阻塞

    Python web框架 Tornado异步非阻塞   异步非阻塞 阻塞式:(适用于所有框架,Django,Flask,Tornado,Bottle) 一个请求到来未处理完成,后续一直等待 解决方案: ...

  3. 关于Python Web框架——Tornado

    关于Tornado的入门看这篇文章,写的非常好: https://zhuanlan.zhihu.com/p/37382503 Tornado 是一个Python web框架和异步网络库,使用非阻塞网络 ...

  4. 异步非阻塞IO的Python Web框架--Tornado

    Tornado的全称是Torado Web Server,从名字上就可知它可用作Web服务器,但同时它也是一个Python Web的开发框架.最初是在FriendFeed公司的网站上使用,FaceBo ...

  5. Python web框架——Tornado

    Tornado是一个Python Web框架和异步网络库,最初由FriendFeed开发.通过使用非阻塞网络I / O,Tornado可以扩展到数万个开放连接,使其成为需要长时间连接每个用户的长轮询, ...

  6. Python Web框架Tornado的异步处理代码演示样例

    1. What is Tornado Tornado是一个轻量级但高性能的Python web框架,与还有一个流行的Python web框架Django相比.tornado不提供操作数据库的ORM接口 ...

  7. Python web框架 Tornado(一)基础学习

    概述 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了 ...

  8. Python web框架 Tornado(二)异步非阻塞

    异步非阻塞 阻塞式:(适用于所有框架,Django,Flask,Tornado,Bottle) 一个请求到来未处理完成,后续一直等待 解决方案:多线程,多进程 异步非阻塞(存在IO请求): Torna ...

  9. Python Web框架篇:Django Form组件

    Form简介 在HTTP中,表单(form标签),是用来提交数据的,其action属性说明了其传输数据的方法:如何传.如何接收. 访问网站时,表单可以实现客户端与服务器之间的通信.例如查询,就用到了表 ...

随机推荐

  1. React中利用axios来实现数据请求

    axios是基于Promise来封装的,通常我们会用axios在数据请求这块作如下配置: 一.拦截器 有注释,不难理解,通常请求头参数不是写死的,应该是去浏览器中读的,例如,login之后返回toke ...

  2. ios 10.3下载 Xcode8配置支持 ios 10.3下载

    一不小心,手机又升级了,哎

  3. caffe中的Local Response Normalization (LRN)有什么用,和激活函数区别

    http://stats.stackexchange.com/questions/145768/importance-of-local-response-normalization-in-cnn ca ...

  4. mysql的master和slave同步方案

    同步原理 master将改变记录到二进制日志(binary log)中 slave将master的binary log events拷贝到它的中继日志(relay log) slave重做中继日志中的 ...

  5. Python IDE in Sublime

    (最近换了电脑,然后忘了把 ST 的配置搬过来,所以重新折腾了一遍 Sublime 中的 Python 环境配置) 以下插件均通过 Package Control 安装. SublimeREPL 快捷 ...

  6. 二次剩余-Cipolla

    二次剩余 \(Cipolla\) 算法 概述 大概就是在模 \(p\) 意义下开根号,如求解方程\(x^2\equiv n(mod\ p)\). 这里只考虑 \(p\) 为素数的情况.若 \(p=2\ ...

  7. bzoj 4811 由乃的OJ

    bzoj 4811 由乃的OJ 考虑树链剖分. 树剖后用一颗线段树维护一段连续区间,类似于一个函数,各位上进入 \(0/1\) ,输出的数字分别是什么.注意到最多只有 \(64\) 位,可以用一个 \ ...

  8. XML专题:使用NSXMLParser解析xml文件

    使用NSXMLParser解析xml文件 1. 设置委托对象,开始解析     NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data ...

  9. cv.Mat 与 .txt 文件数据的读写操作

    1.按OpenCV格式实现的 .txt 文件读写 可以用 cvSave 和 cvLoad 实现,格式和 .xml/.yml 的差不多,不过如果专用与 OpenCV 的数据读写,还是用  .xml/.y ...

  10. Making Genome in Berland (DFS+思维)

    个人心得:被这周的专题名坑了,一直用字典树,明明题目看得很清楚了,不存在相同的字母,即每个字母最多只有一个直接后驱,那么只要用DFS走开头就好了, 思想很巧妙,用vector,记录后驱,同时用visi ...