我们在学习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. 【机器学习PAI实践十】深度学习Caffe框架实现图像分类的模型训练

    背景 我们在之前的文章中介绍过如何通过PAI内置的TensorFlow框架实验基于Cifar10的图像分类,文章链接:https://yq.aliyun.com/articles/72841.使用Te ...

  2. linux给一个文件夹开启权限

    假如要给一个叫做xiaobang的文件夹权限,CD到这一级目录 chmod -R 777 xiaobang

  3. 02-C与OC语言的一些小知识

    1.        #import 跟#include.@class有什么区别?#import<> 跟 #import”"又什么区别? 1>  #import和#inclu ...

  4. LOJ2500 NOIP2014 飞扬的小鸟 【背包DP】*

    LOJ2500 NOIP2014 飞扬的小鸟 LINK 题目大意就是说有n个柱子,在每一秒你可以选择不点下降高度y和点p次上升x∗p,若果当前位置加上x∗p大于上界m,就会停在m. 如果可以成功穿越所 ...

  5. BZOJ1002 FJOI2007 轮状病毒 【基尔霍夫矩阵+高精度】

    BZOJ1002 FJOI2007 轮状病毒 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原 ...

  6. shell编写总结

    变量引用 $(VAR): 会将VAR当做一条命令来执行 '$VAR': 单引号中包含的变量, 不会被引用, 仍然输出$VAR "$VAR": 双引号中包含的变量, 会被引用成$VA ...

  7. gradle 插件

    1. 系统内置插件的应用 a. 二进制 apply plugin :"pluginname" 比如: java b. 脚本插件 apply from : "version ...

  8. Liquibase 了解

    Liquibase 是一个用于跟踪.管理和应用数据库变化的开源的数据库重构工具.它将所有数据库的变化(包括结构和数据)都保存在 XML 文件中,便于版本控制. Liquibase 具备如下特性: 不依 ...

  9. 怎么安装Docker CE 17( Centos 7)

    Docker CE for Centos 7 yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manage ...

  10. Android的AsyncQueryHandler详解

    摘抄别人的博客,看一下,里面有AsyncQueryHandler的详细介绍.http://blog.csdn.net/yuzhiboyi/article/details/8093408 自从frame ...