|
|
b838e2 |
|
|
|
b838e2 |
import time
|
|
|
b838e2 |
import uuid
|
|
|
b838e2 |
import threading
|
|
|
b838e2 |
|
|
|
b838e2 |
|
|
|
b838e2 |
class Session:
|
|
|
b838e2 |
def __init__(self, manager, user_id):
|
|
|
b838e2 |
self.manager = manager
|
|
|
b838e2 |
self.server = manager.server
|
|
|
b838e2 |
self.id = uuid.uuid4().hex
|
|
|
b838e2 |
self.user_id = user_id
|
|
|
b838e2 |
self.maxtime = self.server.config['session']['time']
|
|
|
b838e2 |
self.touch()
|
|
|
b838e2 |
|
|
|
b838e2 |
def touch(self):
|
|
|
b838e2 |
self.time = time.monotonic()
|
|
|
b838e2 |
|
|
|
b838e2 |
def expired(self):
|
|
|
b838e2 |
return self.time + self.maxtime < time.monotonic()
|
|
|
b838e2 |
|
|
|
b838e2 |
|
|
|
b838e2 |
class SessionManager:
|
|
|
b838e2 |
COOKIE='session'
|
|
|
b838e2 |
|
|
|
b838e2 |
def __init__(self, server):
|
|
|
b838e2 |
self.server = server
|
|
|
b838e2 |
self.lock = threading.Lock()
|
|
|
b838e2 |
self.sessions = dict()
|
|
|
b838e2 |
self.timer = threading.Timer(server.config['session']['time']*0.1, self.remove_expired)
|
|
|
b838e2 |
self.timer.start()
|
|
|
b838e2 |
|
|
|
b838e2 |
def remove_expired(self):
|
|
|
b838e2 |
with self.lock:
|
|
|
b838e2 |
remove = list()
|
|
|
b838e2 |
for id, session in self.sessions.items():
|
|
|
b838e2 |
if session.expired():
|
|
|
b838e2 |
remove.append(id)
|
|
|
b838e2 |
for id in remove:
|
|
|
b838e2 |
del self.sessions[id]
|
|
|
b838e2 |
|
|
|
b838e2 |
def delete_by_user_id(self, user_id):
|
|
|
b838e2 |
assert(type(user_id) is int)
|
|
|
b838e2 |
with self.lock:
|
|
|
b838e2 |
remove = list()
|
|
|
b838e2 |
for id, session in self.sessions.items():
|
|
|
b838e2 |
if session.user_id == user_id:
|
|
|
b838e2 |
remove.append(id)
|
|
|
b838e2 |
for id in remove:
|
|
|
b838e2 |
del self.sessions[id]
|
|
|
b838e2 |
|
|
|
b838e2 |
def add_cookie_header(self, request):
|
|
|
b838e2 |
remove = list()
|
|
|
b838e2 |
j = 0
|
|
|
b838e2 |
for i in request.answer.headers:
|
|
|
b838e2 |
if i[0] == 'Set-Cookie':
|
|
|
b838e2 |
remove.insert(0, j)
|
|
|
b838e2 |
j += 1
|
|
|
b838e2 |
for i in remove:
|
|
|
b838e2 |
del request.answer.headers[i]
|
|
|
b838e2 |
|
|
|
b838e2 |
value = None
|
|
|
b838e2 |
if request.session:
|
|
|
b838e2 |
path = self.server.config['urlprefix'] + '/'
|
|
|
b838e2 |
value = '%s=%s; Path=%s; Max-Age=%d; Secure' \
|
|
|
b838e2 |
% (self.COOKIE, request.session.id, path, request.session.maxtime)
|
|
|
b838e2 |
else:
|
|
|
b838e2 |
value = '%s=; Expires=Thu, 01 Jan 1970 00:00:00 GMT' \
|
|
|
b838e2 |
% (self.COOKIE)
|
|
|
b838e2 |
request.answer.headers.append( ('Set-Cookie', value) )
|
|
|
b838e2 |
|
|
|
b838e2 |
def create_session(self, request, user_id):
|
|
|
b838e2 |
assert(type(user_id) is int)
|
|
|
b838e2 |
assert(user_id)
|
|
|
b838e2 |
with self.lock:
|
|
|
b838e2 |
session = Session(self, user_id)
|
|
|
b838e2 |
self.sessions[session.id] = session
|
|
|
b838e2 |
request.session = session
|
|
|
b838e2 |
self.add_cookie_header(request)
|
|
|
b838e2 |
|
|
|
b838e2 |
def attach_session(self, request):
|
|
|
b838e2 |
request.session = None
|
|
|
b838e2 |
|
|
|
b838e2 |
# parse cookie
|
|
|
b838e2 |
id = None
|
|
|
b838e2 |
for i in request.cookie.split(';'):
|
|
|
b838e2 |
j = i.split('=')
|
|
|
b838e2 |
if len(j) == 2:
|
|
|
b838e2 |
if j[0].strip() == self.COOKIE:
|
|
|
b838e2 |
if not id is None: # double cookie equals no cookie
|
|
|
b838e2 |
id = None
|
|
|
b838e2 |
break
|
|
|
b838e2 |
id = j[1].strip()
|
|
|
b838e2 |
|
|
|
b838e2 |
if id:
|
|
|
b838e2 |
with self.lock:
|
|
|
b838e2 |
session = self.sessions.get(id)
|
|
|
b838e2 |
if session:
|
|
|
b838e2 |
if session.expired():
|
|
|
b838e2 |
del self.sessions[id]
|
|
|
b838e2 |
else:
|
|
|
b838e2 |
session.touch()
|
|
|
b838e2 |
request.session = session
|
|
|
b838e2 |
|
|
|
b838e2 |
if request.session or request.cookie: # need we add new or delete existant cookie
|
|
|
b838e2 |
self.add_cookie_header(request)
|
|
|
b838e2 |
|
|
|
b838e2 |
def close_session(self, request):
|
|
|
b838e2 |
if request.session:
|
|
|
b838e2 |
with self.lock:
|
|
|
b838e2 |
if request.session.id in self.sessions:
|
|
|
b838e2 |
del self.sessions[request.session.id]
|
|
|
b838e2 |
request.session = None
|
|
|
b838e2 |
if request.cookie:
|
|
|
b838e2 |
self.add_cookie_header(request)
|