Jeśli chcesz dowiedzieć się więcej o to i wiem jak działa kodowanie lub dekodowanie, jest jakiś odpowiedni kod. Nawiasem mówiąc, wersja Django, której używam, to 1.9.4.
django/contrib/sesje/backendy/base.py
class SessionBase(object):
def _hash(self, value):
key_salt = "django.contrib.sessions" + self.__class__.__name__
return salted_hmac(key_salt, value).hexdigest()
def encode(self, session_dict):
"Returns the given session dictionary serialized and encoded as a string."
serialized = self.serializer().dumps(session_dict)
hash = self._hash(serialized)
return base64.b64encode(hash.encode() + b":" + serialized).decode('ascii')
def decode(self, session_data):
encoded_data = base64.b64decode(force_bytes(session_data))
try:
# could produce ValueError if there is no ':'
hash, serialized = encoded_data.split(b':', 1)
expected_hash = self._hash(serialized)
if not constant_time_compare(hash.decode(), expected_hash):
raise SuspiciousSession("Session data corrupted")
else:
return self.serializer().loads(serialized)
except Exception as e:
# ValueError, SuspiciousOperation, unpickling exceptions. If any of
# these happen, just return an empty dictionary (an empty session).
if isinstance(e, SuspiciousOperation):
logger = logging.getLogger('django.security.%s' %
e.__class__.__name__)
logger.warning(force_text(e))
return {}
django/contrib/sesje/serializer.py ostrości
class JSONSerializer(object):
"""
Simple wrapper around json to be used in signing.dumps and
signing.loads.
"""
def dumps(self, obj):
return json.dumps(obj, separators=(',', ':')).encode('latin-1')
def loads(self, data):
return json.loads(data.decode('latin-1'))
Miejmy na funkcję kodowania SessionBase użytkownika.
- Serializować słownika sesji do json
- utworzyć sól hash
- dodać sól do serializowane sesji base64 konkatenację
Więc dekodowania jest odwrotna. Możemy uprościć funkcję dekodowania w następującym kodzie.
import json
import base64
session_data = 'YTUyYzY1MjUxNzE4MzMxZjNjODFiNjZmZmZmMzhhNmM2NWQzMTllMTp7ImNvdW50Ijo0fQ=='
encoded_data = base64.b64decode(session_data)
hash, serialized = encoded_data.split(b':', 1)
json.loads(serialized.decode('latin-1'))
I to, co zrobił session.get_decoded().
To nie będzie działało dla mnie przy użyciu Pythona 2.7 i Django 1.4. Mój 'base64.decode' wymaga argumentów nazw plików, więc wypróbowałem' base64.b64decode', ale ten zwrócił indeks IndexError: index przypisania poza zasięgiem. Znalazłem obejście (zobacz odpowiedź poniżej), ale jestem ciekawy, dlaczego to nie działa. –
@dolan: zobacz zaktualizowaną odpowiedź, format session_data został zmieniony ze względu na obawy dotyczące bezpieczeństwa. –