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()