|
|
@ -10,6 +10,7 @@ |
|
|
|
:license: BSD, see LICENSE for more details. |
|
|
|
:license: BSD, see LICENSE for more details. |
|
|
|
""" |
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import hashlib |
|
|
|
from datetime import datetime |
|
|
|
from datetime import datetime |
|
|
|
from werkzeug.http import http_date, parse_date |
|
|
|
from werkzeug.http import http_date, parse_date |
|
|
|
from werkzeug.datastructures import CallbackDict |
|
|
|
from werkzeug.datastructures import CallbackDict |
|
|
@ -54,13 +55,13 @@ class TaggedJSONSerializer(object): |
|
|
|
def dumps(self, value): |
|
|
|
def dumps(self, value): |
|
|
|
def _tag(value): |
|
|
|
def _tag(value): |
|
|
|
if isinstance(value, tuple): |
|
|
|
if isinstance(value, tuple): |
|
|
|
return {'##t': [_tag(x) for x in value]} |
|
|
|
return {' t': [_tag(x) for x in value]} |
|
|
|
elif callable(getattr(value, '__html__', None)): |
|
|
|
elif callable(getattr(value, '__html__', None)): |
|
|
|
return {'##m': unicode(value.__html__())} |
|
|
|
return {' m': unicode(value.__html__())} |
|
|
|
elif isinstance(value, list): |
|
|
|
elif isinstance(value, list): |
|
|
|
return [_tag(x) for x in value] |
|
|
|
return [_tag(x) for x in value] |
|
|
|
elif isinstance(value, datetime): |
|
|
|
elif isinstance(value, datetime): |
|
|
|
return {'##d': http_date(value)} |
|
|
|
return {' d': http_date(value)} |
|
|
|
elif isinstance(value, dict): |
|
|
|
elif isinstance(value, dict): |
|
|
|
return dict((k, _tag(v)) for k, v in value.iteritems()) |
|
|
|
return dict((k, _tag(v)) for k, v in value.iteritems()) |
|
|
|
return value |
|
|
|
return value |
|
|
@ -71,11 +72,11 @@ class TaggedJSONSerializer(object): |
|
|
|
if len(obj) != 1: |
|
|
|
if len(obj) != 1: |
|
|
|
return obj |
|
|
|
return obj |
|
|
|
the_key, the_value = obj.iteritems().next() |
|
|
|
the_key, the_value = obj.iteritems().next() |
|
|
|
if the_key == '##t': |
|
|
|
if the_key == ' t': |
|
|
|
return tuple(the_value) |
|
|
|
return tuple(the_value) |
|
|
|
elif the_key == '##m': |
|
|
|
elif the_key == ' m': |
|
|
|
return Markup(the_value) |
|
|
|
return Markup(the_value) |
|
|
|
elif the_key == '##d': |
|
|
|
elif the_key == ' d': |
|
|
|
return parse_date(the_value) |
|
|
|
return parse_date(the_value) |
|
|
|
return obj |
|
|
|
return obj |
|
|
|
return json.loads(value, object_hook=object_hook) |
|
|
|
return json.loads(value, object_hook=object_hook) |
|
|
@ -145,6 +146,13 @@ class SessionInterface(object): |
|
|
|
#: this type. |
|
|
|
#: this type. |
|
|
|
null_session_class = NullSession |
|
|
|
null_session_class = NullSession |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#: A flag that indicates if the session interface is pickle based. |
|
|
|
|
|
|
|
#: This can be used by flask extensions to make a decision in regards |
|
|
|
|
|
|
|
#: to how to deal with the session object. |
|
|
|
|
|
|
|
#: |
|
|
|
|
|
|
|
#: .. versionadded:: 0.10 |
|
|
|
|
|
|
|
pickle_based = False |
|
|
|
|
|
|
|
|
|
|
|
def make_null_session(self, app): |
|
|
|
def make_null_session(self, app): |
|
|
|
"""Creates a null session which acts as a replacement object if the |
|
|
|
"""Creates a null session which acts as a replacement object if the |
|
|
|
real session support could not be loaded due to a configuration |
|
|
|
real session support could not be loaded due to a configuration |
|
|
@ -225,19 +233,36 @@ class SessionInterface(object): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SecureCookieSessionInterface(SessionInterface): |
|
|
|
class SecureCookieSessionInterface(SessionInterface): |
|
|
|
|
|
|
|
"""The default session interface that stores sessions in signed cookies |
|
|
|
|
|
|
|
through the :mod:`itsdangerous` module. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
#: the salt that should be applied on top of the secret key for the |
|
|
|
|
|
|
|
#: signing of cookie based sessions. |
|
|
|
salt = 'cookie-session' |
|
|
|
salt = 'cookie-session' |
|
|
|
session_class = SecureCookieSession |
|
|
|
#: the hash function to use for the signature. The default is sha1 |
|
|
|
|
|
|
|
digest_method = staticmethod(hashlib.sha1) |
|
|
|
|
|
|
|
#: the name of the itsdangerous supported key derivation. The default |
|
|
|
|
|
|
|
#: is hmac. |
|
|
|
|
|
|
|
key_derivation = 'hmac' |
|
|
|
|
|
|
|
#: A python serializer for the payload. The default is a compact |
|
|
|
|
|
|
|
#: JSON derived serializer with support for some extra Python types |
|
|
|
|
|
|
|
#: such as datetime objects or tuples. |
|
|
|
serializer = session_json_serializer |
|
|
|
serializer = session_json_serializer |
|
|
|
|
|
|
|
session_class = SecureCookieSession |
|
|
|
|
|
|
|
|
|
|
|
def get_serializer(self, app): |
|
|
|
def get_signing_serializer(self, app): |
|
|
|
if not app.secret_key: |
|
|
|
if not app.secret_key: |
|
|
|
return None |
|
|
|
return None |
|
|
|
return URLSafeTimedSerializer(app.secret_key, |
|
|
|
signer_kwargs = dict( |
|
|
|
salt=self.salt, |
|
|
|
key_derivation=self.key_derivation, |
|
|
|
serializer=self.serializer) |
|
|
|
digest_method=self.digest_method |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
return URLSafeTimedSerializer(app.secret_key, salt=self.salt, |
|
|
|
|
|
|
|
serializer=self.serializer, |
|
|
|
|
|
|
|
signer_kwargs=signer_kwargs) |
|
|
|
|
|
|
|
|
|
|
|
def open_session(self, app, request): |
|
|
|
def open_session(self, app, request): |
|
|
|
s = self.get_serializer(app) |
|
|
|
s = self.get_signing_serializer(app) |
|
|
|
if s is None: |
|
|
|
if s is None: |
|
|
|
return None |
|
|
|
return None |
|
|
|
val = request.cookies.get(app.session_cookie_name) |
|
|
|
val = request.cookies.get(app.session_cookie_name) |
|
|
@ -253,15 +278,15 @@ class SecureCookieSessionInterface(SessionInterface): |
|
|
|
def save_session(self, app, session, response): |
|
|
|
def save_session(self, app, session, response): |
|
|
|
domain = self.get_cookie_domain(app) |
|
|
|
domain = self.get_cookie_domain(app) |
|
|
|
path = self.get_cookie_path(app) |
|
|
|
path = self.get_cookie_path(app) |
|
|
|
httponly = self.get_cookie_httponly(app) |
|
|
|
|
|
|
|
secure = self.get_cookie_secure(app) |
|
|
|
|
|
|
|
if not session: |
|
|
|
if not session: |
|
|
|
if session.modified: |
|
|
|
if session.modified: |
|
|
|
response.delete_cookie(app.session_cookie_name, |
|
|
|
response.delete_cookie(app.session_cookie_name, |
|
|
|
domain=domain, path=path) |
|
|
|
domain=domain, path=path) |
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
httponly = self.get_cookie_httponly(app) |
|
|
|
|
|
|
|
secure = self.get_cookie_secure(app) |
|
|
|
expires = self.get_expiration_time(app, session) |
|
|
|
expires = self.get_expiration_time(app, session) |
|
|
|
val = self.get_serializer(app).dumps(dict(session)) |
|
|
|
val = self.get_signing_serializer(app).dumps(dict(session)) |
|
|
|
response.set_cookie(app.session_cookie_name, val, |
|
|
|
response.set_cookie(app.session_cookie_name, val, |
|
|
|
expires=expires, httponly=httponly, |
|
|
|
expires=expires, httponly=httponly, |
|
|
|
domain=domain, path=path, secure=secure) |
|
|
|
domain=domain, path=path, secure=secure) |
|
|
|