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()
作者: honmaple
链接: https://honmaple.me/articles/2017/08/tornado中session实现.html
版权: CC BY-NC-SA 4.0 知识共享署名-非商业性使用-相同方式共享4.0国际许可协议
wechat
alipay

加载评论