tornado中默认没有session的实现,虽然默认的 set_secure_cookie 已经足够安全了,但更安全的应该是客户端保存session_id,服务端保存对应的信息
注:保存在redis中的经测试是可以的,保存在内存中的貌似还不行
给出源码:
1from uuid import uuid4
2from redis import StrictRedis
3from functools import wraps
4from datetime import datetime, timedelta
5from pytz import timezone
6
7
8def singleton(cls):
9 instances = {}
10
11 @wraps(cls)
12 def getinstance(*args, **kw):
13 if cls not in instances:
14 instances[cls] = cls(*args, **kw)
15 return instances[cls]
16
17 return getinstance
18
19
20def current_time(tz=None):
21 if tz is None:
22 tz = 'UTC'
23 return datetime.now(timezone(tz))
24
25
26class CoreSession(object):
27 def __setitem__(self, key, value):
28 '''
29 session['username'] = 'hello'
30 '''
31 return self.set(key, value)
32
33 def __getitem__(self, key):
34 return self.get(key)
35
36 def get_or_set(self, key, value):
37 if not self.get(key):
38 self.set(key, value)
39 return self.get(key)
40
41
42@singleton
43class MemorySession(CoreSession):
44 def __init__(self):
45 '''
46 self._client = {'session_id1':{key:value},
47 'session_id2':{key:value}}
48 '''
49 self._client = {}
50
51 def init(self, session_id, expires_days=30):
52 self.session_id = 'session:{}'.format(session_id)
53 self.expires_days = expires_days
54 if self.session_id not in self._client:
55 self._client[self.session_id] = {
56 'is_authenticated': False,
57 'expire': current_time() + timedelta(days=self.expires_days)
58 }
59 print(self.session_id)
60
61 def set(self, key, value):
62 self._client[self.session_id][key] = value
63
64 def get(self, key):
65 return self._client[self.session_id].get(key)
66
67 def pop(self, key):
68 return self._client[self.session_id].pop(key, None)
69
70 def remove_expires(self):
71 expire_sessions = []
72 for key, value in self._client.items():
73 if value['expire'] > current_time():
74 expire_sessions.append(key)
75
76 def clear(self):
77 del self._client[self.session_id]
78
79
80@singleton
81class RedisSession(CoreSession):
82 def __init__(self):
83 self._client = StrictRedis(
84 host='localhost',
85 port=6379,
86 db=0,
87 password='redis',
88 decode_responses=True)
89
90 def init(self, session_id, expires_days=30):
91 self.session_id = 'session:{}'.format(session_id)
92 self.expires_days = expires_days
93 if not self._client.exists(self.session_id):
94 self._client.hset(self.session_id, 'is_authenticated', 0)
95 self._client.expire(self.session_id, self.expires_days * 30 * 3600)
96
97 def set(self, key, value):
98 return self._client.hset(self.session_id, key, value)
99
100 def get(self, key):
101 return self._client.hget(self.session_id, key)
102
103 def pop(self, key):
104 return self._client.hdel(self.session_id, key)
105
106 def clear(self):
107 return self._client.delete(self.session_id)
108
109
110class Session(object):
111 def __init__(self, request_handler):
112 self.request_handler = request_handler
113 self.session_id = self.request_handler.get_secure_cookie("session")
114 if not self.session_id:
115 self.session_id = str(uuid4())
116 self.request_handler.set_secure_cookie("session", self.session_id)
117 # get cookies is bytes
118 if isinstance(self.session_id, bytes):
119 self.session_id = self.session_id.decode()
120 self._session = RedisSession()
121 # self._session = MemorySession()
122 self._session.init(self.session_id)
123
124 def __setitem__(self, key, value):
125 self._session[key] = value
126
127 def __getitem__(self, key):
128 return self._session[key]
129
130 def clear(self):
131 self.request_handler.clear_cookie(self.session_id)
132 return self._session.clear()
知识共享署名-非商业性使用-相同方式共享4.0国际许可协议