In response to some discussion on Chapter 20 of the Django book, I'd like to submit my first contrib package for consideration, a middleware package that transparently implements signed cookies. It uses the SECRET_KEY setting already included in Django, and could easily be modified to allow different encryption algorithms (currently it simply uses md5). The only configuration is the addition of the package to MIDDLEWARE_CLASSES, everything else is handled automatically.
A note on using this with other middlewares. Its position in the middleware class list defines which other middlewares receive the security of signed cookies, but there's slightly more to it than that. In order to ensure that the values passed for further processing are in fact valid, any cookies not containing a valid signature will be removed from the HttpRequest instance. For the most part, this is fine, as long as this middleware is placed before any other middlewares that use cookies. The only potential advantage to placing a cookie-using middleware after this one is a savings of 33 characters per cookie, which can sometimes help, given the length restriction on cookie values. However, in the case of SessionMiddleware (and perhaps others), the value stored is known to just be an ID, and not any actual usable values. For this case, it's safe to place SessionMiddleware before this one, and it will work as usual, with the advantage that the 'sessionid' cookie will not incur the additional 33 characters taken up by the signing process. However, this also also means that the 'sessionid' cookie will not be available to any middlewares listed after this one, nor will it be available in the view. SessionMiddleware stores the session_key it its own internal structure, so this shouldn't actually pose any real-world problems. It's just a caveat that should be known in case it's used with other middlewares where it might cause problems. The code for middleware.py follows (I've placed it in django.contrib.signed_cookies, but any other name would suffice): import re try: from hashlib import md5 as hash except ImportError: from md5 import new as hash from django.conf import settings regex = re.compile(r'([0-9a-f]+):(.*)$') class SignedCookiesMiddleware(object): def process_request(self, request): for (key, signed_value) in request.COOKIES.items(): try: (signature, value) = regex.match(signed_value).groups() assert signature == self.get_digest(key, value) request.COOKIES[key] = value except: del request.COOKIES[key] def process_response(self, request, response): for (key, morsel) in response.cookies.items(): if morsel['expires'] == 0 and morsel['max-age'] == 0: continue digest = self.get_digest(key, morsel.value) response.set_cookie(key, '%s:%s' % (digest, morsel.value), max_age=morsel['max-age'], expires=morsel['expires'], path=morsel['path'], domain=morsel['domain'], secure=morsel['secure'] ) return response def get_digest(self, key, value): string = ':'.join([settings.SECRET_KEY, key, value]) return hash(string).hexdigest() --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---