2010-11-04 5 views
15

Nella tabella django_session viene memorizzato il tavolo session_data che viene prima sottoposto al pickle con il modulo pickle di python e quindi codificato in base64 utilizzando il modulo base64 di python.come trovare l'id utente da session_data dalla tabella django_session?

Ho ottenuto il decodificato session_data decodificato.

session_data da tavolo django_session:

gAJ9cQEoVQ9fc2Vzc2lvbl9leHBpcnlxAksAVRJfYXV0aF91c2VyX2JhY2tlbmRxA1UpZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmRxBFUNX2F1dGhfdXNlcl9pZHEFigECdS5iZmUwOWExOWI0YTZkN2M0NDc2MWVjZjQ5ZDU0YjNhZA== 

dopo aver decodificato dal 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 

Voglio scoprire auth_user_id da auth_user_idq\x05\x8a\x01\x02u . Per favore aiutami a farlo.

risposta

25

Ho avuto problemi con il metodo di Paulo (vedi il mio commento sulla sua risposta), così ho finito per usare questo metodo da 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: formato cambiato da quando la risposta originale, per 1,4 e sopra vedere l'aggiornamento sotto

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} 

[update]

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

Io davvero non so perché ho usato il modulo Base64, Immagino perché la domanda lo ha caratterizzato.

si può semplicemente utilizzare il metodo str.decode: è un rischio per la sicurezza

>>> 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.

Caricamento in salamoia i dati provenienti da fonti utente (cookie), quindi il formato session_data è stato cambiato da quando la questione è stata risolta (dovrei segui il problema specifico nel bug tracker di Django e collegalo qui, ma la mia pausa pomodoro è sparita).

Il formato ora (da Django 1.4) è "hash: json-object" dove il primo hash da 40 byte è una crittografia e il resto è un payload JSON. Per ora è possibile ignorare l'hash (consente di verificare se i cookie non sono stati manomessi da alcuni cookie hacker).

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

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. –

+1

@dolan: vedere la risposta aggiornata, il formato sessione_data modificato a causa di problemi di sicurezza. –

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

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.

  1. serializzare l'dizionario sessione per un JSON
  2. creare un sale hash
  3. 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.

Problemi correlati