Secure Cookie
This module implements a cookie that is not alterable from the clientbecause it adds a checksum the server checks for. You can use it assession replacement if all you have is a user id or something to marka logged in user.
Keep in mind that the data is still readable from the client as anormal cookie is. However you don’t have to store and flush thesessions 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 unserializemethod will fail silently and return a new empty SecureCookie object.
Keep in mind that the values will be visible in the cookie so do notstore data in a cookie you don’t want the user to see.
Application Integration
If you are using the werkzeug request objects you could integrate thesecure cookie into your application like this:
from werkzeug.utils import cached_property
from werkzeug.wrappers import BaseRequest
from werkzeug.contrib.securecookie import SecureCookie
# don't use this key but a different one; you could just use
# os.urandom(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)
Security
The default implementation uses Pickle as this is the only module thatused to be available in the standard library when this module was created.If you have simplejson available it’s strongly recommended to create asubclass and replace the serialization method:
import json
from werkzeug.contrib.securecookie import SecureCookie
class JSONSecureCookie(SecureCookie):
serialization_method = json
The weakness of Pickle is that if someone gains access to the secret keythe attacker can not only modify the session but also execute arbitrarycode on the server.
Reference
- class _werkzeug.contrib.securecookie.SecureCookie(_data=None, secret_key=None, new=True)
- Represents a secure cookie. You can subclass this class and providean alternative mac method. The import thing is that the mac methodis a function with a similar interface to the hashlib. Requiredmethods 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
参数:
- data – the initial data. Either a dict, list of tuples or None.
- secret_key – the secret key. If not set None or not specifiedit has to be set before serialize() is called.
- new – The initial value of the new flag.
- new
True if the cookie was newly created, otherwise False
- Whenever an item on the cookie is set, this attribute is set to True.However this does not track modifications inside mutable objectsin 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 thatshould_save can pick it up.
- hash_method()
The hash method to use. This has to be a module with a new functionor a function that creates a hashlib object. Such as _hashlib.md5_Subclasses can override this attribute. The default hash is sha1.Make sure to wrap this in staticmethod() if you store an arbitraryfunction there such as hashlib.sha1 which might be implementedas a function.
classmethod _load_cookie(_request, key='session', secret_key=None)
- Loads a SecureCookie from a cookie in request. If thecookie is not set, a new SecureCookie instanced isreturned.
参数:
- **request** – a request object that has a _cookies_ attributewhich is a dict of all cookie values.
- **key** – the name of the cookie.
- **secret_key** – the secret key used to unquote the cookie.Always provide the value even though it hasno default!
- classmethod _quote(_value)
- Quote the value for the cookie. This can be any object supportedby serialization_method.
参数:value – the value to quote.
- quotebase64 = True_
if the contents should be base64 quoted. This can be disabled if theserialization process returns cookie safe strings only.
savecookie(_response, key='session', expires=None, session_expires=None, max_age=None, path='/', domain=None, secure=None, httponly=False, force=False)
- Saves the SecureCookie in a cookie on response object. Allparameters that are not described here are forwarded directlyto set_cookie().
参数:
- **response** – a response object that has aset_cookie() method.
- **key** – the name of the cookie.
- **session_expires** – the expiration date of the secure cookiestored information. If this is not providedthe cookie _expires_ date is used instead.
- serializationmethod =
_ the module used for serialization. Unless overriden by subclassesthe standard pickle module is used.
- Serialize the secure cookie into a string.
If expires is provided, the session will be automatically invalidatedafter expiration when you unseralize it. This provides betterprotection against session cookie theft.
参数:expires – an optional expiration date for the cookie (adatetime.datetime object)
- should_save
True if the session should be saved. By default this is only truefor modified cookies, not new.
- Unquote the value for the cookie. If unquoting does not work aUnquoteError is raised.
参数:value – the value to unquote.
参数:
- **string** – the cookie value to unserialize.
- **secret_key** – the secret key used to serialize the cookie.返回:
a new SecureCookie.