tornado中默认没有session的实现,虽然默认的 set_secure_cookie 已经足够安全了,但更安全的应该是客户端保存session_id,服务端保存对应的信息
注:保存在redis中的经测试是可以的,保存在内存中的貌似还不行
给出源码:
from uuid import uuid4
from redis import StrictRedis
from functools import wraps
from datetime import datetime, timedelta
from pytz import timezone
def singleton(cls):
instances = {}
@wraps(cls)
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
def current_time(tz=None):
if tz is None:
tz = 'UTC'
return datetime.now(timezone(tz))
class CoreSession(object):
def __setitem__(self, key, value):
'''
session['username'] = 'hello'
'''
return self.set(key, value)
def __getitem__(self, key):
return self.get(key)
def get_or_set(self, key, value):
if not self.get(key):
self.set(key, value)
return self.get(key)
@singleton
class MemorySession(CoreSession):
def __init__(self):
'''
self._client = {'session_id1':{key:value},
'session_id2':{key:value}}
'''
self._client = {}
def init(self, session_id, expires_days=30):
self.session_id = 'session:{}'.format(session_id)
self.expires_days = expires_days
if self.session_id not in self._client:
self._client[self.session_id] = {
'is_authenticated': False,
'expire': current_time() + timedelta(days=self.expires_days)
}
print(self.session_id)
def set(self, key, value):
self._client[self.session_id][key] = value
def get(self, key):
return self._client[self.session_id].get(key)
def pop(self, key):
return self._client[self.session_id].pop(key, None)
def remove_expires(self):
expire_sessions = []
for key, value in self._client.items():
if value['expire'] > current_time():
expire_sessions.append(key)
def clear(self):
del self._client[self.session_id]
@singleton
class RedisSession(CoreSession):
def __init__(self):
self._client = StrictRedis(
host='localhost',
port=6379,
db=0,
password='redis',
decode_responses=True)
def init(self, session_id, expires_days=30):
self.session_id = 'session:{}'.format(session_id)
self.expires_days = expires_days
if not self._client.exists(self.session_id):
self._client.hset(self.session_id, 'is_authenticated', 0)
self._client.expire(self.session_id, self.expires_days * 30 * 3600)
def set(self, key, value):
return self._client.hset(self.session_id, key, value)
def get(self, key):
return self._client.hget(self.session_id, key)
def pop(self, key):
return self._client.hdel(self.session_id, key)
def clear(self):
return self._client.delete(self.session_id)
class Session(object):
def __init__(self, request_handler):
self.request_handler = request_handler
self.session_id = self.request_handler.get_secure_cookie("session")
if not self.session_id:
self.session_id = str(uuid4())
self.request_handler.set_secure_cookie("session", self.session_id)
# get cookies is bytes
if isinstance(self.session_id, bytes):
self.session_id = self.session_id.decode()
self._session = RedisSession()
# self._session = MemorySession()
self._session.init(self.session_id)
def __setitem__(self, key, value):
self._session[key] = value
def __getitem__(self, key):
return self._session[key]
def clear(self):
self.request_handler.clear_cookie(self.session_id)
return self._session.clear()