My favorites | Sign in
Project Home Downloads Wiki Issues
Project Information
Members
Featured
Downloads

gmemsess

gmemsess is a secure lightweight memcache-backed session class for Google appengine. It is only suitable for short-term sessions, for providing your own authentication system or shopping cart, for instance. gmemsess is in use in at least one commercial application, and depending on memcache for data storage (rather than the datastore) has now been well proven.

Security Features

gmemsess works by storing an eight-character session ID in a cookie on the client's browser. Each character can be an upper- or lower-case letter, giving almost 10^14 (hundred trillion) possible session IDs, so an attacker trying to guess the session ID will take rather a long time.

Apart from the session ID, all session data is stored in appengine's memcache, so attackers cannot access it (unless they hack appengine, in which case everything is lost anyway).

Memcache

Memcache has benefits and drawbacks. The benefits are that it is fast and it's timeout feature handles session timeouts neatly, allowing gmemsess to be much smaller (and faster).

The main drawback is that memcache does not guarantee storage in any way. According to Google, it may disappear at any time, when resources are limited, or the memcache system is reset for instance. This means sessions may die mysteriously, and your users will have to log back in, or start shopping again. In practise this does not seem to happen.

Long Term Sessions

To handle long term sessions (days/weeks/months), gmemsess would need significant changes to make it write to the datastore as well as memcache. If you need this, please contact me at greg@vig.co.nz.

Integration with Django, CherryPy, WebPy...

There have been some requests to modify gmemsess to work with the various web frameworks. I'm reluctant to do this because it will more than double the size and complexity of the code, and I love simplicity.

Simplicity means you can't use gmemsess with your framework out of the box - but it also means that it is easy to modify gmemsess any way you want. Have a look at the code in gemmesess.py - I think you'll be surprised how little there is. All you need to do is pass your framework's container into gmemsess instead of the request handler rh, and then use the container's request and response objects instead of rh.request and rh.response. See here for an example for CherryPy.

Another solution is to send your framework's developers a link to gmemmsess - again, that simplicity means they should be able to integrate it into their framework with little trouble. Most frameworks seem to need modifications for AppEngine, so it makes sense to build gmemsess directly into the framework.


Documentation

__init__(rh,name,timeout)

Create a session object.
  • rh -- the parent's request handler (usually self)
  • name -- the cookie name (defaults to "gsid")
  • timeout -- the number of seconds the session will last between requests (defaults to 1800 secs - 30 minutes)

invalidate()

Delete session data and cookie.

is_new()

Returns True if session was created during this request.

get_id()

Returns the session ID as a string.

save()

Save session data. No arguments.

Using gmemsess

A gmemsess session works just like a python dictionary, so you can add as many key/value pairs as you like. To get started, download gmemsess1.4.zip and extract gmemsess.py into your project directory.

  • In your code, add import gmemsess
  • To make a session called sess, add sess=gmemsess.Session(self)
  • To find out if this is a new session, use if sess.is_new():
  • To store something, use sess['something']='Do as you would be done to'
  • Access or change something with sess['something']
  • To delete something, use del sess['something']
  • After storing/changing/deleting something, do sess.save() to make it permanent
  • To end the session, use sess.invalidate()

Here's a really simple example:

#!/usr/bin/env python

import gmemsess
import wsgiref.handlers
from google.appengine.ext import webapp

#----------------------------------------------------------------------
class MainHandler(webapp.RequestHandler):
	#----------------------------------------------------------
	def get(self):
		sess=gmemsess.Session(self)
		if sess.is_new():
			self.response.out.write('New session - setting counter to 0.<br>')
			sess['myCounter']=0
			sess.save()
		else:
			sess['myCounter']+=1
			self.response.out.write('Session counter is %d.'%sess['myCounter'])
			if sess['myCounter']<3:
				sess.save()
			else:
				self.response.out.write(' Invalidating cookie.')
				sess.invalidate()


#------------------------------------------------------------
def main():
	application=webapp.WSGIApplication([('/',MainHandler)],debug=True)
	wsgiref.handlers.CGIHandler().run(application)


if __name__=='__main__':
	main()

Hit your browser's refresh button several times to see it working.

Powered by Google Project Hosting