session object for werkzeug with sqlalchemy. This one use SessionStore object distributed with werkzeug
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)
Example of session support on werkzeug (http://werkzeug.pocco.org) with sqlachemy. All session data are saved in database in a pickle objet. Session is a simple dict.This is based on django session system.
1 # -*- coding: utf-8 -*-
2 # example of session support on werkzeug with sqlachemy
3 # all session data are saved in database in a
4 # pickle objet. session is a simple dict.
5 # This is based on django session system.
6 #
7 # To add a variable to the session :
8 # request.session['variable'] = value
9 #
10 # to get a variable :
11 # request.session['variable'] or request.session.get('variable')
12 #
13 # To delete a variable :
14 # del request.session['variable']
15 #
16 # .......
17 #
18 # Setup :
19 # you have to set these settings :
20 # SESSION_COOKIE_NAME = 'SID'
21 # SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
22 # SESSION_COOKIE_DOMAIN = None
23 # SESSION_COOKIE_PATH = '/'
24 # SESSION_COOKIE_SECURE = False
25 #
26 # DBSession is a basic sqlalchemy session
27 # related to your wsgi application.
28 # to use session you have to override BaseRequest
29 # object like this :
30 #
31 # class Request(BaseRequest):
32 # charset = 'utf-8'
33 #
34 # def __init__(self, app, environ):
35 # super(Request, self).__init__(environ)
36 # self.app = app
37 # session_key = self.cookies.get(settings.SESSION_COOKIE_NAME)
38 # self.session = SessionStore(session_key)
39 #
40 # session is saved by your application when a data
41 # is modified. Add this somehere in your wsgi application
42 # where you get your response object :
43 #
44 # try:
45 # modified = request.session.modified
46 # accessed = request.session.accessed
47 # except:
48 # pass
49 # else:
50 # if modified:
51 # max_age = settings.SESSION_COOKIE_AGE
52 # expires = time.time() + settings.SESSION_COOKIE_AGE
53 # request.session.save()
54 # response.set_cookie(settings.SESSION_COOKIE_NAME,
55 # request.session.session_key,
56 # expires=expires, max_age = max_age,
57 # path=settings.SESSION_COOKIE_PATH,
58 # domain=settings.SESSION_COOKIE_DOMAIN,
59 # secure=settings.SESSION_COOKIE_SECURE)
60 #
61
62 session_table = Table('session', metadata,
63 Column('session_key', Unicode(40), primary_key=True),
64 Column('session_data', Binary),
65 Column('expire_date', DateTime)
66 )
67
68
69
70
71 import base64
72 from datetime import datetime, timedelta
73 import os
74 import md5
75 import random
76 import sys
77 import time
78 import cPickle as pickle
79
80 from database import DBSession
81 import settings
82
83 from sqlalchemy.orm import synonym
84
85 class SuspiciousOperation(Exception):
86 pass
87
88 class Session(object):
89 def __init__(self, session_key, session_data=None, expire_date=None):
90 self.session_key = session_key
91 self.session_data = session_data
92 self.expire_date = expire_date
93
94 def __repr__(self):
95 return "<%s(%s)>" % (self.__class__.__name__ , self.session_key)
96
97 def _encode(self, session_data):
98 pickled = pickle.dumps(session_data)
99 pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
100 self._session_data = base64.encodestring(pickled + pickled_md5)
101
102 def _decode(self):
103 encoded_data = base64.decodestring(self._session_data)
104 pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
105 if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
106 raise SuspiciousOperation, "User tampered with session cookie."
107 try:
108 return pickle.loads(pickled)
109 # Unpickling can cause a variety of exceptions. If something happens,
110 # just return an empty dictionary (an empty session).
111 except:
112 return {}
113
114 session_data = property(_decode, _encode)
115
116 DBSession.mapper(Session, session_table, properties = {
117 'session_data':synonym('_session_data', map_column=True)
118 })
119
120
121
122 class SessionBase(object):
123 def __init__(self, session_key = None):
124 self._session_key = session_key
125 self.accessed = False
126 self.modified = False
127
128 def __contains__(self, key):
129 return key in self._session
130
131 def __getitem__(self, key):
132 return self._session[key]
133
134 def __setitem__(self, key, value):
135 self._session[key]=value
136 self.modified = True
137
138 def __delitem__(self, key):
139 del self._session['key']
140 self.modified = True
141
142 def items(self):
143 return self._session.items()
144
145 def keys(self):
146 return self._session.keys()
147
148 def get(self, key, default=None):
149 return self._session.get(key, default)
150
151 def pop(self, key, *args):
152 self.modified = self.modified or key in self._session
153 return self._session.pop(key, *args)
154
155 def setdefault(self, key, value):
156 if key in self._session:
157 return self._session[key]
158 else:
159 self.modified = True
160 self._session[key] = value
161 return value
162
163 def _get_new_session_key(self):
164 "Returns session key that isn't being used."
165 # The random module is seeded when this Apache child is created.
166 # Use settings.SECRET_KEY as added salt.
167 try:
168 pid = os.getpid()
169 except AttributeError:
170 # No getpid() in Jython, for example
171 pid = 1
172 while 1:
173 session_key = md5.new(u"%s%s%s%s" % (random.randint(0, sys.maxint - 1),
174 pid, time.time(), settings.SECRET_KEY)).hexdigest()
175 if not self.exists(session_key):
176 break
177 return session_key
178
179 def _get_session_key(self):
180 if self._session_key:
181 return self._session_key.decode()
182 else:
183 self._session_key = self._get_new_session_key()
184 return self._session_key.decode()
185
186 def _set_session_key(self, session_key):
187 self._session_key = session_key
188
189 session_key = property(_get_session_key, _set_session_key)
190
191 def _get_session(self):
192 # Lazily loads session from storage.
193 self.accessed = True
194 try:
195 return self._session_cache
196 except AttributeError:
197 if self._session_key is None:
198 self._session_cache = {}
199 else:
200 self._session_cache = self.load()
201 return self._session_cache
202
203 _session = property(_get_session)
204
205 def exists(self, session_key):
206 raise NotImplementedError
207
208 def save(self):
209 """
210 Saves the session data.
211 """
212 raise NotImplementedError
213
214 def delete(self, session_key):
215 """
216 Clears out the session data under this key.
217 """
218 raise NotImplementedError
219
220 def load(self):
221 """
222 Loads the session data and returns a dictionary.
223 """
224 raise NotImplementedError
225
226
227 class SessionStore(SessionBase):
228 def __init__(self, session_key=None):
229 super(SessionStore, self).__init__(session_key)
230
231 def load(self):
232 s=DBSession.query(Session).filter(Session.session_key==self.session_key).first()
233 if s:
234 return s.session_data
235 else:
236 self.session_key = self._get_new_session_key()
237 self._session_cache = {}
238 self.save()
239 self.modified = True
240 return {}
241
242 def exists(self, session_key):
243 try:
244 DBSession.query(Session).get(session_key=session_key)
245 except:
246 return False
247 return True
248
249 def save(self):
250 s = DBSession.query(Session).get(self.session_key)
251 if s:
252 s.session_data = self._session
253 expire_date = datetime.now() + timedelta(seconds=settings.SESSION_COOKIE_AGE)
254 else:
255 s=Session(
256 session_key=self.session_key,
257 session_data=self._session,
258 expire_date = datetime.now() + timedelta(seconds=settings.SESSION_COOKIE_AGE)
259 )
260 DBSession.expunge(s)
261 DBSession.save_or_update(s)
262 DBSession.commit()
263
264 def delete(self, session_key):
265 try:
266 DBSession.delete(DBSession.query(Session).get(session_key=session_key))
267 except:
268 pass
269 return {}
Pages : 1