自定义Tornado的session组件

时间:2021-02-02 00:08:50

session和cookie的关系

cookie:保存在客户端浏览器上的键值对
session_id = "eyJ1c2VyX2luZm8iOiJ" session:保存在服务器上的键值对
{
"eyJ1c2VyX2luZm8iOiJ":{'is_login':True, 'user':'standby',...},
"iJhbGV4In0.DYUE4A.A":{'is_login':True, 'user':'alex',...},
...
} - 用户第一次打开浏览器请求我的网站页面
- 在服务器端生成一个随机字符串,作为value发给客户端浏览器。
- 这个随机字符串在服务器的session中作为key,value={},保存起来。

知识准备

1. 通过给定字符串,如何实例化一个对象出来?

import importlib
path = "session_code.RedisSession"
md,cls = path.rsplit('.',maxsplit=1)
m = importlib.import_module(md)
cls = getattr(m,cls)
print(cls.__name__)

或者

import importlib
path = "scrapy.middleware.MiddlewareManager"
tmp_li = path.split('.')
cls_name = tmp_li.pop()
prefix = '.'.join(tmp_li)
m = importlib.import_module(prefix)
cls = getattr(m,cls_name)
print(cls.__name__)

rest_framework/setting.py

def import_from_string(val, setting_name):
"""
Attempt to import a class from a string representation.
"""
try:
# Nod to tastypie's use of importlib.
module_path, class_name = val.rsplit('.', 1)
module = import_module(module_path)
return getattr(module, class_name)
except (ImportError, AttributeError) as e:
msg = "Could not import '%s' for API setting '%s'. %s: %s." % (val, setting_name, e.__class__.__name__, e)
raise ImportError(msg)

from django.utils.module_loading import import_string

def import_string(dotted_path):
"""
Import a dotted module path and return the attribute/class designated by the
last name in the path. Raise ImportError if the import failed.
"""
try:
module_path, class_name = dotted_path.rsplit('.', 1)
except ValueError:
msg = "%s doesn't look like a module path" % dotted_path
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2]) module = import_module(module_path) try:
return getattr(module, class_name)
except AttributeError:
msg = 'Module "%s" does not define a "%s" attribute/class' % (
module_path, class_name)
six.reraise(ImportError, ImportError(msg), sys.exc_info()[2])

2. 面向对象里的 __setitem__ __getitem__

class Foo(object):
def __getitem__(self, item):
return "123"
def __setitem__(self, key, value):
self.__dict__[key] = value
def __delitem__(self, key):
print('----')
self.__dict__.pop(key) obj = Foo()
print(obj['k1']) # __getitem__ obj['k1'] = 666 # __setitem__ del obj['k1'] # __delitem__ Django 里面操作session:
request.session['xxx'] = xxxxx

3. 程序结合配置文件以及工厂模式

class MemSession(object):
def __getitem__(self, item):
return "123" def __setitem__(self, key, value):
self.__dict__[key] = value def __delitem__(self, key):
print('----')
self.__dict__.pop(key) class RedisSession(object):
def __getitem__(self, item):
return "123" def __setitem__(self, key, value):
self.__dict__[key] = value def __delitem__(self, key):
print('----')
self.__dict__.pop(key) class SessionFactory(object):
"""
工厂模式
settings.py : SESSION_ENGINE = "session_code.RedisSession"
""" @staticmethod
def get_session(self):
import settings
engine = settings.SESSION_ENGINE
import importlib
module_path,cls_name = engine.split('.',maxsplit=1)
md = importlib.import_module(module_path)
cls = getattr(md,cls_name)
return cls

  

Tornado基于内存和redis的session组件实现示例

app.py

from tornado import ioloop
from tornado.web import RequestHandler,Application
from session_code import SessionFactory settings = {
'template_path':'templates',
} class SessionHandler(object):
def initialize(self):
cls = SessionFactory.get_session()
self.session = cls(self) class IndexHandler(SessionHandler,RequestHandler): def get(self):
user = self.session['user']
if user:
self.write("首页欢迎你")
else:
self.redirect('/login') class LoginHandler(SessionHandler,RequestHandler): def get(self):
self.render('login.html',msg="")
def post(self, *args, **kwargs):
name = self.get_argument('name')
pwd = self.get_argument('pwd')
if 'alex'==name and '123' == pwd:
self.session['user'] = name
self.redirect('/index')
else:
self.render('login.html',msg="用户名或密码错误") application = Application([
(r"/index", IndexHandler,{},'alias_name1'),
(r"/login", LoginHandler,{},'alias_name2'),
],**settings) if __name__ == "__main__":
application.listen(8090)
ioloop.IOLoop.instance().start()

session_code.py

import json
import time
import hashlib
import settings def gen_random_str():
md5 = hashlib.md5()
md5.update(str(time.time()).encode('utf-8'))
return md5.hexdigest() class MemSession(object):
''' 静态字段在类里只保存一份(不管实例化多少次,用的都是同一份) '''
container = {} def __init__(self,handler):
self.handler = handler
self.session_id = settings.SESSION_ID
self.expires = settings.EXPIRES
self.initial() def initial(self):
client_random_str = self.handler.get_cookie(self.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] = {} # 给服务端设置session
expires = time.time() + self.expires
self.handler.set_cookie(self.session_id,self.random_str,expires=expires) # 给客户端设置cookie def __getitem__(self, item):
return self.container[self.random_str].get(item) def __setitem__(self, key, value):
self.container[self.random_str][key] = value
print(self.container) 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.EXPIRES
self.initial() def get_redis_conn(self):
import redis
conn = redis.Redis(host='8.8.8.8', port=6379)
return conn def initial(self):
self.redis_conn = self.get_redis_conn()
client_random_str = self.handler.get_cookie(self.session_id)
if client_random_str and self.redis_conn.exists(client_random_str):
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) # 给客户端设置cookie
self.redis_conn.expire(self.random_str,self.expires) # 给redis设置超时时间 def __getitem__(self, item):
# redis 返回的是byte类型,所以需要decode
data_str = self.redis_conn.hget(self.random_str,item)
if data_str:
return json.loads(data_str.decode('utf-8')) def __setitem__(self, key, value):
# val = {'type':type(value).__name__,'value':value}
self.redis_conn.hset(self.random_str,key,json.dumps(value)) def __delitem__(self, key):
self.redis_conn.hdel(self.random_str,key) class SessionFactory(object):
"""
工厂模式
"""
@staticmethod
def get_session():
import settings
engine = settings.SESSION_ENGINE
import importlib
module_path,cls_name = engine.split('.',maxsplit=1)
md = importlib.import_module(module_path)
cls = getattr(md,cls_name)
return cls

settings.py

SESSION_ENGINE = "session_code.RedisSession"
SESSION_ID = "__session_id__"
EXPIRES = 300

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <h1 class="c1">Login</h1>
<form action="" method="post">
<input type="text" name="name">
<input type="text" name="pwd">
<input type="submit" value="提交"> {{ msg }}
</form> </body>
</html>

  

自定义Tornado的session组件的更多相关文章

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

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

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

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

  3. Web框架之Django&lowbar;08 重要组件(form组件、cookie和session组件)

    摘要: form组件 cookie组件 session组件 一.form组件 form介绍我们之前在html页面中利用form表单向后端提交数据时候,都需要对用户的输入进行校验,比如校验用户是否输入正 ...

  4. Combo&lpar; 自定义下拉框&rpar; 组件

    本节课重点了解 EasyUI 中 Combo(自定义下拉框)组件的使用方法,这个组件依赖于ValidateBox(验证框)组件 一. 加载方式自定义下拉框不能通过标签的方式进行创建.<input ...

  5. 第二百一十二节,jQuery EasyUI,Combo&lpar;自定义下拉框&rpar;组件

    jQuery EasyUI,Combo(自定义下拉框)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 Combo(自定义下拉框)组件的使用方 ...

  6. MongoDB实践-自定义ASP&period;NET Session Store

    Session由来 由于HTTP协议是无状态的,客户端与服务器端进行“请求-响应”操作后,建立的连接就释放了,服务器端根本不知道刚才是哪个客户端访问的.但是有些场景是需要知道客户端的状态的,最典型的就 ...

  7. Vue 使用use、prototype自定义自己的全局组件

    使用Vue.use()写一个自己的全局组件. 目录如下: 然后在Loading.vue里面定义自己的组件模板 <template> <div v-if="loadFlag& ...

  8. Flask框架【七】—session组件详解

    一.flask session简介 flask中session组件可分为内置的session组件还有第三方flask-session组件,内置的session组件缺点: 功能单一 session是保存 ...

  9. Django框架(十六)—— cookie和session组件

    目录 cookie和session组件 一.cookie 1.cookie的由来 2.什么是cookie 3.cookie的原理 4.cookie的覆盖 5.在浏览器中查看cookie 6.cooki ...

随机推荐

  1. 【开学季】自学嵌入式开发&vert;四核开发板&vert;4412开发板&vert;ARM&plus;Android&plus;linux技术

    淘宝店铺:迅为开发板http://arm-board.taobao.com 网站:http://www.topeetboard.com QQ咨询:2551456065 电话咨询:010-5895758 ...

  2. jeewx的使用&lowbar;01 接入和验证

    jeewx是java语言的用于开发微信公共平台的一个框架,有人说很臃肿,但个人感觉还不错,仁者见仁智者见智吧, 下面简单介绍工作原理: 1.下载 要使用jeewx需要先下载其源码 jeewx介绍:ht ...

  3. Generative Adversarial Nets&lbrack;Theory&amp&semi;MSE&rsqb;

    本文来自<deep multi-scale video prediction beyond mean square error>,时间线为2015年11月,LeCun等人的作品. 从一个视 ...

  4. 查看Sql Server 数据库的内存使用情况

    -- 查询SqlServer总体的内存使用情况 select type , sum(virtual_memory_reserved_kb) VM_Reserved , sum(virtual_memo ...

  5. 艾妮记账本微信小程序开发(失败版)

    这是一个寒假假期作业,要求是用web开发或者微信小程序或者手机app开发的,我本来是打算用微信小程序开发的,但由于这个后台数据库连接需要通过https认证后的浏览器再访问MySQL.所以做到后台数据库 ...

  6. canvas-简单快速实现知乎登录页背景效果

    前言 打开知乎的登录页,就可以看到其背景有一个动效,看起来好像蛮不错的样子: 这个效果使用canvas是不难实现的,接下来就一步一步地讲解并实现这个效果. 分析 在动工之前先分析这个效果到底是如何运动 ...

  7. ThinkPHP 小于5&period;0&period;24 远程代码执行高危漏洞 修复方案

    漏洞描述由于ThinkPHP5.0框架对Request类的method处理存在缺陷,导致黑客构造特定的请求,可直接GetWebShell. 漏洞评级严重 影响版本ThinkPHP 5.0系列 < ...

  8. CH&num;17C 舞动的夜晚

    原题链接 即求二分图的不可行边数量,因为不保证是完备匹配,所以需要通过网络流求出任意一组最大匹配,并建立新图判断. 建新图:对于跑完网络流的图上已经匹配的边,建立反边:对于没有匹配的边,建立正边(图只 ...

  9. &lbrack;ActionScript 3&period;0&rsqb; 幻灯片效果实例

    package com.fylibs.components.effects { import com.fylibs.utils.LoaderQueues; import com.tweener.tra ...

  10. 【原创】MapReduce程序如何在集群上执行

    首先了解下资源调度管理框架Yarn. Yarn的结构(如图): Resource Manager (rm)负责调度管理整个集群上的资源,而每一个计算节点上都会有一个Node Manager(nm)来负 ...