2010-11-04 21 views
15

En django_session se almacena la tabla session_data que primero se decapa usando el módulo pickle de python y luego se codifica en base64 utilizando el módulo base64 de python.cómo encontrar el ID de usuario de session_data de la tabla django_session?

Obtuve el decodificado pickled session_data.

datos_sesion de la mesa django_session:

gAJ9cQEoVQ9fc2Vzc2lvbl9leHBpcnlxAksAVRJfYXV0aF91c2VyX2JhY2tlbmRxA1UpZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmRxBFUNX2F1dGhfdXNlcl9pZHEFigECdS5iZmUwOWExOWI0YTZkN2M0NDc2MWVjZjQ5ZDU0YjNhZA== 

después de la decodificación por base64.decode (datos_sesion):

\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 auth_user_id de auth_user_idq\x05\x8a\x01\x02u . Por favor, ayúdame a hacerlo.

Respuesta

25

tuve problemas con el método de Paulo (ver mi comentario sobre su respuesta), así que terminamos usando este método desde un scottbarnham.com blog post:

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 
10

NOTA: El formato ha cambiado desde respuesta original, por 1,4 y por encima de ver la actualización más adelante

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} 

[Actualización]

My base64.decode requires filename arguments, so then I tried base64.b64decode, but this returned "IndexError: list assignment index out of range".

Realmente no sé por qué he utilizado el módulo de base 64, Supongo que porque la pregunta lo presentaba.

sólo puede utilizar el str.decode método:

>>> pickle.loads(session_data.decode('base64')) 
{'_auth_user_id': 2L, '_auth_user_backend': 'django.contrib.auth.backends.ModelBackend', 
'_session_expiry': 0} 

I found a work-around (see answer below), but I am curious why this doesn't work.

Cargando escabeche datos de fuentes de usuario (cookies) es un riesgo de seguridad, por lo que el formato de datos_sesion fue cambiado desde que se respondió a esta pregunta (yo debería ir después del problema específico en el rastreador de errores de Django y vincularlo aquí, pero mi ruptura pomodoro se ha ido).

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 útil JSON. Por ahora puede ignorar el hash (permite verificar si los datos no fueron manipulados por algún pirata informático).

>>> json.loads(session_data.decode('base64')[41:]) 
{u'_auth_user_backend': u'django.contrib.auth.backends.ModelBackend', 
u'_auth_user_id': 1} 
+0

Esto no funcionaría para mí usando Python 2.7 y Django 1.4. 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". Encontré una solución alternativa (ver respuesta a continuación), pero tengo curiosidad de por qué esto no funciona. –

+1

@dolan: vea la respuesta actualizada, el formato session_data ha cambiado debido a problemas de seguridad. –

2
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) 
1

Si desea obtener más información sobre y sabe cómo codifica o decodifica el trabajo, hay algún código relevante. Por cierto, la versión de Django que uso es 1.9.4.

django/contrib/sesiones/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/sesiones/serializer.py enfoque

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')) 

Vamos en la función de codificación de SessionBase.

  1. serializar el diccionario sesión a un JSON
  2. crear una sal de hash
  3. añadir la sal a la sesión serializado, Base64 la concatenación

Así, decodificar 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 que session.get_decoded() hizo.

Cuestiones relacionadas