snippet: view plain - save this
1 # -*- coding: utf-8 -*-
2 """"
3 example of session support on werkzeug with sqlachemy
4 all session data are saved in database. It override
5 SessionStore object from werkzeug.contrib.sessions
6
7 Setup :
8 you have to set these settings :
9 SESSION_COOKIE_NAME = 'SID'
10 SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
11 SESSION_COOKIE_DOMAIN = None
12 SESSION_COOKIE_PATH = '/'
13 SESSION_COOKIE_SECURE = False
14
15 DBSession is a basic sqlalchemy session
16 related to your wsgi application.
17
18 store and session object directly in the application dispatching::
19
20 session_store = FilesystemSessionStore()
21
22 def application(environ, start_response):
23 request = Request(environ)
24 sid = request.cookie.get('cookie_name')
25 if sid is None:
26 request.session = session_store.new()
27 else:
28 request.session = session_store.get(sid)
29 response = get_the_response_object(request)
30 if request.session.should_save:
31 max_age = settings.SESSION_COOKIE_AGE
32 expires = time.time() + settings.SESSION_COOKIE_AGE
33 session_store.save(request.session)
34 response.set_cookie(settings.SESSION_COOKIE_NAME,
35 request.session.sid,
36 expires=expires, max_age = max_age,
37 path=settings.SESSION_COOKIE_PATH,
38 domain=settings.SESSION_COOKIE_DOMAIN,
39 secure=settings.SESSION_COOKIE_SECURE)
40
41 return response(environ, start_response)
42 """"
43
44
45
46 from datetime import datetime, timedelta
47 import base64
48 import md5
49 import random
50 import cPickle as pickle
51
52 from sqlalchemy.orm import synonym
53
54 from werkzeug.contrib.sessions import Session,SessionStore
55
56 from database import DBSession
57 import settings
58
59 session_table = Table('session', metadata,
60 Column('session_key', Unicode(40), primary_key=True),
61 Column('session_data', Binary),
62 Column('expire_date', DateTime)
63 )
64
65 class SuspiciousOperation(Exception):
66 pass
67
68 class SessionModel(object):
69 def __init__(self, session_key, session_data=None, expire_date=None):
70 self.session_key = session_key
71 self.session_data = session_data
72 self.expire_date = expire_date
73
74 def __repr__(self):
75 return "<%s(%s)>" % (self.__class__.__name__ , self.session_key)
76
77 def _encode(self, session_data):
78 pickled = pickle.dumps(session_data)
79 pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
80 self._session_data = base64.encodestring(pickled + pickled_md5)
81
82 def _decode(self):
83 encoded_data = base64.decodestring(self._session_data)
84 pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
85 if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
86 raise SuspiciousOperation, "User tampered with session cookie."
87 try:
88 return pickle.loads(pickled)
89 # Unpickling can cause a variety of exceptions. If something happens,
90 # just return an empty dictionary (an empty session).
91 except:
92 return {}
93
94 session_data = property(_decode, _encode)
95
96 DBSession.mapper(SessionModel, session_table, properties = {
97 'session_data':synonym('_session_data', map_column=True)
98 })
99
100 class DatabaseSessionStore(SessionStore):
101 def __init__(self, session_class=Session):
102 SessionStore.__init__(self, session_class)
103
104 def save(self, session):
105 s = DBSession.query(SessionModel).get(session.sid)
106 if s:
107 s.session_data = dict(session)
108 expire_date = datetime.now() + timedelta(seconds=settings.SESSION_COOKIE_AGE)
109 else:
110 s=SessionModel(
111 session_key=session.sid,
112 session_data=dict(session),
113 expire_date = datetime.now() + timedelta(seconds=settings.SESSION_COOKIE_AGE)
114 )
115 DBSession.expunge(s)
116 DBSession.save_or_update(s)
117 DBSession.commit()
118
119 def delete(self, session):
120 try:
121 DBSession.delete(DBSession.query(SessionModel).get(session_key=session.sid))
122 except:
123 pass
124 return {}
125
126 def get(self, sid):
127 s=DBSession.query(SessionModel).filter(SessionModel.session_key==sid).first()
128 if not s or not self.is_valid_key(sid):
129 return self.new()
130
131 return self.session_class(s.session_data, sid, False)

0 comments