python - ¿Cómo encontrar el ID de usuario de session_data de la tabla django_session?
pickle pinax (4)
NOTA: el formato ha cambiado desde la respuesta original, para 1.4 y superior consulte la actualización a continuación
import pickle
data = pickle.loads(base64.decode(session_data))
>>> print data
{''_auth_user_id'': 2L, ''_auth_user_backend'': ''django.contrib.auth.backends.ModelBackend'',
''_session_expiry'': 0}
[actualizar]
Mi base64.decode requiere argumentos de nombre de archivo, entonces probé base64.b64decode, pero esto devolvió "IndexError: índice de asignación de lista fuera de rango".
Realmente no sé por qué usé el módulo base64, supongo que porque la pregunta lo presentaba.
Puedes usar el método str.decode
:
>>> pickle.loads(session_data.decode(''base64''))
{''_auth_user_id'': 2L, ''_auth_user_backend'': ''django.contrib.auth.backends.ModelBackend'',
''_session_expiry'': 0}
Encontré una solución alternativa (vea la respuesta a continuación), pero tengo curiosidad de por qué esto no funciona.
Cargar datos de fuentes de usuario (cookies) es un riesgo para la seguridad, por lo que se cambió el formato de session_data desde que se respondió esta pregunta (debo ir tras el problema específico en el rastreador de errores de Django y vincularlo aquí, pero mi ruptura de pomodoro desapareció).
El formato ahora (desde Django 1.4) es "hash: json-object", donde el primer hash de 40 bytes es una firma criptográfica y el resto es una carga JSON. Por ahora, puede ignorar el hash (permite verificar si los datos no fueron manipulados por algún hacker de cookies).
>>> json.loads(session_data.decode(''base64'')[41:])
{u''_auth_user_backend'': u''django.contrib.auth.backends.ModelBackend'',
u''_auth_user_id'': 1}
En la tabla django_session
, session_data
se almacena, que primero se conserva utilizando el módulo pickle de python y luego se codifica en base64 mediante el módulo base64 de python.
Tengo la sesión decodificada decodificación_data.
session_data de la tabla django_session:
gAJ9cQEoVQ9fc2Vzc2lvbl9leHBpcnlxAksAVRJfYXV0aF91c2VyX2JhY2tlbmRxA1UpZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmRxBFUNX2F1dGhfdXNlcl9pZHEFigECdS5iZmUwOWExOWI0YTZkN2M0NDc2MWVjZjQ5ZDU0YjNhZA==
después de decodificarlo por base64.decode (session_data):
/x80/x02}q/x01(U/x0f_session_expiryq/x02K/x00U/x12_auth_user_backendq/x03U)django.contrib.auth.backends.ModelBackendq/x04U/r_auth_user_idq/x05/x8a/x01/x02u.bfe09a19b4a6d7c44761ecf49d54b3ad
Quiero averiguar el valor de auth_user_id
en auth_user_idq/x05/x8a/x01/x02u
. Por favor ayúdame a hacerlo.
Si desea obtener más información al respecto y saber cómo funciona la codificación o la descodificación, hay algunos códigos relevantes. Por cierto, la versión de Django que uso es la 1.9.4.
django / contrib / session / backends / 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 / session / serializer.py
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''))
Centrémonos en la función de codificación de SessionBase.
- Serializar el diccionario de la sesión a un json
- crear una sal de hash
- agregar la sal a la sesión serializada, base64 la concatenación
Entonces, la decodificación es inversa. Podemos simplificar la función de decodificación en el siguiente código.
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''))
Y eso lo hizo session.get_decoded ().
Tuve problemas con el método de Paulo (ver mi comentario sobre su respuesta), así que terminé usando este método de una publicación en el blog de scottbarnham.com :
from django.contrib.sessions.models import Session
from django.contrib.auth.models import User
session_key = ''8cae76c505f15432b48c8292a7dd0e54''
session = Session.objects.get(session_key=session_key)
uid = session.get_decoded().get(''_auth_user_id'')
user = User.objects.get(pk=uid)
print user.username, user.get_full_name(), user.email
from django.conf import settings
from django.contrib.auth.models import User
from django.utils.importlib import import_module
def get_user_from_sid(session_key):
django_session_engine = import_module(settings.SESSION_ENGINE)
session = django_session_engine.SessionStore(session_key)
uid = session.get(''_auth_user_id'')
return User.objects.get(id=uid)