Se volete saperne di più su e sa come funziona la codifica o decodifica, ci sono alcuni codici rilevanti. A proposito la versione di Django che uso è 1.9.4.
Django/contrib/sessioni/backend/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/sessioni/serializer.py attenzione
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'))
Let sulla funzione di codifica di SessionBase.
- serializzare l'dizionario sessione per un JSON
- creare un sale hash
- aggiungere il sale alla sessione serializzato, BASE64 la concatenazione
Quindi, decodificare è inversa. Possiamo semplificare la funzione di decodifica nel seguente codice.
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'))
E che ciò che session.get_decoded() ha fatto.
Questo non funzionerebbe con Python 2.7 e Django 1.4. Il mio 'base64.decode' richiede gli argomenti del nome del file, quindi ho provato' base64.b64decode', ma questo ha restituito "IndexError: list assignment index out of range". Ho trovato un work-around (vedi risposta sotto), ma sono curioso perché questo non funziona. –
@dolan: vedere la risposta aggiornata, il formato sessione_data modificato a causa di problemi di sicurezza. –