python django pickle pinax

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.

  1. Serializar el diccionario de la sesión a un json
  2. crear una sal de hash
  3. 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)