tornado中session实现
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()
