This module implements a cookie that is not alterable from the client because it adds a checksum the server checks for. You can use it as session replacement if all you have is a user id or something to mark a logged in user.
Keep in mind that the data is still readable from the client as a normal cookie is. However you don’t have to store and flush the sessions you have at the server.
Example usage:
>>> from werkzeug.contrib.securecookie import SecureCookie
>>> x = SecureCookie({"foo": 42, "baz": (1, 2, 3)}, "deadbeef")
Dumping into a string so that one can store it in a cookie:
>>> value = x.serialize()
Loading from that string again:
>>> x = SecureCookie.unserialize(value, "deadbeef")
>>> x["baz"]
(1, 2, 3)
If someone modifies the cookie and the checksum is wrong the unserialize method will fail silently and return a new empty SecureCookie object.
Keep in mind that the values will be visible in the cookie so do not store data in a cookie you don’t want the user to see.
If you are using the werkzeug request objects you could integrate the secure cookie into your application like this:
from werkzeug import BaseRequest, cached_property
from werkzeug.contrib.securecookie import SecureCookie
# don't use this key but a different one; you could just use
# os.unrandom(20) to get something random
SECRET_KEY = '\xfa\xdd\xb8z\xae\xe0}4\x8b\xea'
class Request(BaseRequest):
@cached_property
def client_session(self):
data = self.cookies.get('session_data')
if not data:
return SecureCookie(secret_key=SECRET_KEY)
return SecureCookie.unserialize(data, SECRET_KEY)
def application(environ, start_response):
request = Request(environ, start_response)
# get a response object here
response = ...
if request.client_session.should_save:
session_data = request.client_session.serialize()
response.set_cookie('session_data', session_data,
httponly=True)
return response(environ, start_response)
A less verbose integration can be achieved by using shorthand methods:
class Request(BaseRequest):
@cached_property
def client_session(self):
return SecureCookie.load_cookie(self, secret_key=COOKIE_SECRET)
def application(environ, start_response):
request = Request(environ, start_response)
# get a response object here
response = ...
request.client_session.save_cookie(response)
return response(environ, start_response)
Represents a secure cookie. You can subclass this class and provide an alternative mac method. The import thing is that the mac method is a function with a similar interface to the hashlib. Required methods are update() and digest().
Example usage:
>>> x = SecureCookie({"foo": 42, "baz": (1, 2, 3)}, "deadbeef")
>>> x["foo"]
42
>>> x["baz"]
(1, 2, 3)
>>> x["blafasel"] = 23
>>> x.should_save
True
Parameters: |
|
---|
Whenever an item on the cookie is set this is set to True. However this does not track modifications inside mutable objects in the cookie:
>>> c = SecureCookie()
>>> c["foo"] = [1, 2, 3]
>>> c.modified
True
>>> c.modified = False
>>> c["foo"].append(4)
>>> c.modified
False
In that situation it has to be set to modified by hand so that should_save can pick it up.
Loads a SecureCookie from a cookie in request. If the cookie is not set, a new SecureCookie instanced is returned.
Parameters: |
|
---|
Quote the value for the cookie. This can be any object supported by serialization_method.
Parameter: | value – the value to quote. |
---|
Saves the SecureCookie in a cookie on response object. All parameters that are not described here are forwarded directly to set_cookie().
Parameters: |
|
---|
Serialize the secure cookie into a string.
If expires is provided, the session will be automatically invalidated after expiration when you unseralize it. This provides better protection against session cookie theft.
Parameter: | expires – an optional expiration date for the cookie (a datetime.datetime object) |
---|
Unquote the value for the cookie. If unquoting does not work a UnquoteError is raised.
Parameter: | value – the value to unquote. |
---|
Load the secure cookie from a serialized string.
Parameters: |
|
---|---|
Returns: | a new SecureCookie. |