|
@@ -0,0 +1,86 @@
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+from flask.sessions import SessionInterface, SessionMixin
|
|
|
|
+from werkzeug.datastructures import CallbackDict
|
|
|
|
+
|
|
|
|
+from sqlalchemy import Table, Column, String, LargeBinary, DateTime,\
|
|
|
|
+ select, delete, insert, update
|
|
|
|
+
|
|
|
|
+from random import SystemRandom, randrange
|
|
|
|
+import string
|
|
|
|
+from datetime import datetime, timedelta
|
|
|
|
+import cPickle
|
|
|
|
+
|
|
|
|
+random=SystemRandom()
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class SQLSession(CallbackDict, SessionMixin):
|
|
|
|
+
|
|
|
|
+ def __init__(self, sid, db, table, new=False, initial=None):
|
|
|
|
+ self.sid=sid
|
|
|
|
+ self.db=db
|
|
|
|
+ self.table=table
|
|
|
|
+ self.modified=False
|
|
|
|
+ self.new=new
|
|
|
|
+ def _on_update(self):
|
|
|
|
+ self.modified=True
|
|
|
|
+ super(SQLSession, self).__init__(initial, _on_update)
|
|
|
|
+
|
|
|
|
+ def save(self):
|
|
|
|
+ if self.new:
|
|
|
|
+ self.db.execute(self.table.insert({
|
|
|
|
+ 'session_id': self.sid,
|
|
|
|
+ 'expire': datetime.now()+timedelta(hours=1),
|
|
|
|
+ 'value': cPickle.dumps(dict(self), -1)
|
|
|
|
+ }))
|
|
|
|
+ self.new=False
|
|
|
|
+ else:
|
|
|
|
+ self.db.execute(self.table.update(
|
|
|
|
+ self.table.c.session_id == self.sid,
|
|
|
|
+ {
|
|
|
|
+ 'expire': datetime.now()+timedelta(hours=1),
|
|
|
|
+ 'value': cPickle.dumps(dict(self), -1)
|
|
|
|
+ }
|
|
|
|
+ ))
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class MySessionInterface(SessionInterface):
|
|
|
|
+ def __init__(self, engine, metadata):
|
|
|
|
+ self.engine = engine
|
|
|
|
+
|
|
|
|
+ self.table = Table('flask_sessions', metadata,
|
|
|
|
+ Column('session_id', String(32), primary_key=True),
|
|
|
|
+ Column('expire', DateTime, index=True),
|
|
|
|
+ Column('value', LargeBinary, nullable=False)
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ def open_session(self, app, request):
|
|
|
|
+ sid = request.cookies.get(app.session_cookie_name)
|
|
|
|
+ if sid:
|
|
|
|
+ res=self.engine.execute(select([self.table.c.value], (self.table.c.session_id == sid) &
|
|
|
|
+ (self.table.c.expire > datetime.now()))).first()
|
|
|
|
+ if res:
|
|
|
|
+ return SQLSession(sid, self.engine, self.table, False, cPickle.loads(res[0]))
|
|
|
|
+
|
|
|
|
+ while True:
|
|
|
|
+ sid=''.join(random.choice(string.ascii_letters+string.digits) for i in range(32))
|
|
|
|
+ res=self.engine.execute(select([self.table.c.value], self.table.c.session_id == sid)).first()
|
|
|
|
+ if not res:
|
|
|
|
+ break
|
|
|
|
+
|
|
|
|
+ return SQLSession(sid, self.engine, self.table, True)
|
|
|
|
+
|
|
|
|
+ def save_session(self, app, session, response):
|
|
|
|
+ if session.modified:
|
|
|
|
+ session.save()
|
|
|
|
+
|
|
|
|
+ # remove expired sessions.. or maybe not
|
|
|
|
+ if randrange(20) % 20 == 0:
|
|
|
|
+ self.engine.execute(self.table.delete(self.table.c.expire <= datetime.now()))
|
|
|
|
+
|
|
|
|
+ response.set_cookie(app.session_cookie_name, session.sid,
|
|
|
|
+ expires=self.get_expiration_time(app, session),
|
|
|
|
+ domain=self.get_cookie_domain(app),
|
|
|
|
+ path=self.get_cookie_path(app),
|
|
|
|
+ secure=self.get_cookie_secure(app),
|
|
|
|
+ httponly=self.get_cookie_httponly(app))
|