自定义session

在tornado中,所有的请求都是由RequestHandler对象来处理(以下简称handler对象)。在RequestHandler源码中,预留了一个钩子方法initialize,该方法会在实例化Handler对象时执行。因此,如果我们继承RequestHandler类并重写initialize,就可以完成一些自定义操作。

  • 定义一个Session类,其实例化时接收handler对象
    • 在Session类中定义一个静态字段(大字典),用来存储session_id和对应的用户信息;所有的session对象都可以访问这个大字典。
    • 在Session的构造方法中,获取和设置cookie:
      • 调用handler对象get_cookie()方法获取session_id,如果没有,则生成一段随机字符串random_str作为session_id
      • 将session_id写入大字典
      • 调用handler对象的set_cookie()方法,通知浏览器设置cookie:set-cookie: {session_id: random_str}
    • 在Session类中,定义getitem, setitem, delitem方法来实现通过字典的方式操作session对象(面向对象内置方法参考这里)
  • 在initialize方法中为handler对象增加session属性,其值是Session对象:self.session=Session(self);在每个路由对应的视图中都重写initialize方法太麻烦了,利用面向对象的多继承,将这一步单独写在一个类SessionHandler,所以视图类先继承这个类即可。
  • 每次请求进来,都会执行SessionHandler中的initialize方法,并实例化Session对象,从而获取session_id
  • 操作session:
    • 通过self.session[key] = value 即可调用session对象的setitem方法来写session;
    • 通过self.session[key] 即可调用session对象的getitem方法来获取session
    • 通过del self.session[key] 即可调用session对象的delitem方法来删除session
    • 通过self.session.delete(),即可调用session对象的delete方法,删除整个session_id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import tornado.ioloop
import tornado.web
from hashlib import sha1
import os
import time


# 随机生成session_id
create_session_id = lambda: sha1(bytes('%s%s' % (os.urandom(16), time.time()), encoding='utf-8')).hexdigest()


class Session:
"""自定义session"""

info_container = {
# session_id: {'user': info} --> 通过session保存用户信息,权限等
}

def __init__(self, handler):
"""
初始化时传入RequestHandler对象,通过它进行cookie操作
self.handler.set_cookie()
self.handler.get_cookie()
:param handler:
"""
self.handler = handler

# 从 cookie 中获取作为 session_id 的随机字符串,如果没有或不匹配则生成 session_id
random_str = self.handler.get_cookie('session_id')
if (not random_str) or (random_str not in self.info_container):
random_str = create_session_id()
self.info_container[random_str] = {}
self.random_str = random_str

# 每次请求进来都会执行set_cookie,保证每次重置过期时间为当前时间以后xx秒以后
self.handler.set_cookie('session_id', random_str, max_age=60)

def __getitem__(self, item):
return self.info_container[self.random_str].get(item)

def __setitem__(self, key, value):
self.info_container[self.random_str][key] = value

def __delitem__(self, key):
if self.info_container[self.random_str].get(key):
del self.info_container[self.random_str][key]

def delete(self):
"""从大字典删除session_id"""
del self.info_container[self.random_str]


class SessionHandler:
def initialize(self):
self.session = Session(self) # handler增加session属性


class LoginHandler(SessionHandler, tornado.web.RequestHandler):
def get(self):
self.render('login.html')

def post(self):
user = self.get_argument('user')
pwd = self.get_argument('pwd')
if user == 'lena' and pwd == '123':
self.session['user'] = user
self.redirect('/index')


class IndexHandler(SessionHandler, tornado.web.RequestHandler):
def get(self):
user = self.session['user'] # 注意这里不能用session.get('user')
if not user:
self.redirect('/login')
return

self.write('你好啊,%s'% user) # 返回响应

settings = {
'template_path': 'templates',
'cookie_secret': 'asdfasdfasd', # 签名cookie加盐
}

application = tornado.web.Application([
(r'/login', LoginHandler),
(r'/index', IndexHandler),
], **settings)


if __name__ == '__main__':
application.listen(8080)
tornado.ioloop.IOLoop.instance().start()

转载Ayhan_huang博客http://blog.csdn.net/ayhan_huang/article/details/78731783