from hashlib import sha1
import pickle
import settings
COOKIE_NAME_ERROR = 'flash-error'
COOKIE_NAME_NOTICE = 'flash-notice'
def flash_error(msg):
Flash.set_error = msg
def flash_notice(msg):
Flash.set_notice = msg
def context_processor(request):
if COOKIE_NAME_ERROR in request.COOKIES:
Flash.error = _decode(request.COOKIES[COOKIE_NAME_ERROR])
elif Flash.set_error:
Flash.error, Flash.set_error = Flash.set_error, None
if COOKIE_NAME_NOTICE in request.COOKIES:
Flash.notice = _decode(request.COOKIES[COOKIE_NAME_NOTICE])
elif Flash.set_notice:
Flash.notice, Flash.set_notice = Flash.set_notice, None
return {'flash': Flash}
class Middleware(object):
def process_request(self, request):
Flash.clear()
def process_response(self, request, response):
if Flash.set_error:
response.set_cookie(COOKIE_NAME_ERROR, _encode(Flash.set_error))
else:
response.delete_cookie(COOKIE_NAME_ERROR)
if Flash.set_notice:
response.set_cookie(COOKIE_NAME_NOTICE, _encode(Flash.set_notice))
else:
response.delete_cookie(COOKIE_NAME_NOTICE)
return response
def _encode(value):
value = pickle.dumps(value)
hash = sha1(value + settings.SECRET_KEY)
return '%s$%s' % (hash.hexdigest(), value)
def _decode(cookie):
s = cookie.split('$', 1)
if not s or len(s) != 2:
return None
hash, value = s
if sha1(value + settings.SECRET_KEY).hexdigest() != hash:
return None
return pickle.loads(value)
class Flash(object):
@classmethod
def clear(cls):
cls.error = None
cls.notice = None
cls.set_error = None
cls.set_notice = None
Comments
Hi alexk,
Your code unpickles data from an untrusted source (the cookie). This is a bad idea: http://www.python.org/doc/2.2.1/lib/pickle-sec.html
Besides, you absolutely don't need to store the messages in a cookie, i.e. client-side. Storing them server-side until you get to render them is safer, and arguably makes more sense. Look here for a snippet that does just this: http://www.djangosnippets.org/snippets/1002/
(Unrelatedly, why is Flash a class and not an object?)
Good work otherwise, keep it up! :)
#
Sundance is right. Unless this code were integrated with signed cookies, it should be considered dangerously insecure.
#
Thanks guys, I will revamp my code.
#
I fixed the code. The cookies are now prefixed with a salted hash value which is checked before unpickling. Thanks again!
#
I see two problems:
The class Flash is a global variable, which is shared by all threads. I would prefer to store the messages on the request object.
I would use a list of messages. Something like this:
#
Snippet 1459 is my implementation of cookie based messages.
#