как найти идентификатор пользователя из session_data из таблицы django_session? - PullRequest
20 голосов
/ 04 ноября 2010

В django_session хранится таблица session_data, которая сначала обрабатывается с помощью модуля python для pickle, а затем кодируется в base64 с помощью модуля python base64.

Я получил декодированные данные сеанса с расширением.

сессия_данных из таблицы django_session:

gAJ9cQEoVQ9fc2Vzc2lvbl9leHBpcnlxAksAVRJfYXV0aF91c2VyX2JhY2tlbmRxA1UpZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmRxBFUNX2F1dGhfdXNlcl9pZHEFigECdS5iZmUwOWExOWI0YTZkN2M0NDc2MWVjZjQ5ZDU0YjNhZA==

после декодирования с помощью 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

Я хочу узнать значение auth_user_id из auth_user_idq\x05\x8a\x01\x02u.Пожалуйста, помогите мне сделать это.

Ответы [ 6 ]

32 голосов
/ 21 августа 2012

У меня были проблемы с методом Пауло (см. Мой комментарий к его ответу), поэтому я в итоге использовал этот метод из 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
12 голосов
/ 04 ноября 2010

ПРИМЕЧАНИЕ: формат изменен с момента первоначального ответа, для версии 1.4 и выше см. Обновление ниже

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}

[обновление]

Мой base64.decode требует аргументов имени файла, поэтому я попробовал base64.b64decode, но это вернуло «IndexError: список назначенных индексов вне диапазона».

Я действительно не знаю, почему я использовал модуль base64, я думаю, потому что вопрос содержал его.

Вы можете просто использовать метод str.decode:

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

Я нашел обходной путь (см. Ответ ниже), но мне любопытно, почему это не работает.

Загрузка маринованных данных из пользовательских источников (куки) представляет угрозу безопасности, поэтому формат session_data был изменен с момента ответа на этот вопрос (я должен перейти к конкретной проблеме в трекере ошибок Django и связать ее здесь, но мой pomodoro перерыв ушел).

Теперь формат (начиная с Django 1.4) - это «hash: json-object», где первый 40-байтовый хэш является криптосигнатурой, а остальные - полезной нагрузкой JSON. На данный момент вы можете игнорировать хеш (он позволяет проверить, не были ли данные взломаны каким-либо хакером).

>>> json.loads(session_data.decode('base64')[41:])
{u'_auth_user_backend': u'django.contrib.auth.backends.ModelBackend',
 u'_auth_user_id': 1}
3 голосов
/ 11 апреля 2016

Если вы хотите узнать больше об этом и узнать, как работает кодирование или декодирование, есть некоторые соответствующие коды.Кстати, версия Django, которую я использую, это 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'))

Давайте сосредоточимся на функции кодирования SessionBase.

  1. Сериализация словаря сеансов в формате json
  2. , создание хеш-соли
  3. , добавлениесоль для сериализованного сеанса, base64 конкатенация

Итак, декодирование является обратным.Мы можем упростить функцию декодирования в следующем коде.

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

И то, что сделал session.get_decoded ().

3 голосов
/ 16 октября 2013
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)
0 голосов
/ 26 июня 2019

Мне просто нужно было решить что-то подобное при установке Django.Я знал ID (36) пользователя и хотел удалить данные сеанса для этого конкретного пользователя.Я хотел выпустить этот код в качестве прототипа для сборки для поиска пользователя в данных сеанса:

from django.contrib.sessions.models import Session

TARGET_USER = 36  # edit this to match  target user.

TARGET_USER = str(TARGET_USER)  # type found to be a string

for session in Session.objects.all():
    raw_session= session.get_decoded()
    uid = session.get_decoded().get('_auth_user_id')
    if uid == TARGET_USER:  # this could be a list also if multiple users
        print(session)
        # session.delete()  # uncomment to delete session data associated with the user

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 07 февраля 2019

Я хотел сделать это на чистом Python с последней версией DJango (2.05). Вот что я сделал:

>>> import base64
>>> x = base64.b64decode('OWNkOGQxYjg4NzlkN2ZhOTc2NmU1ODY0NWMzZmQ4YjdhMzM4OTJhNjp7Im51bV92aXNpdHMiOjJ9')
>>> print(x)
b'9cd8d1b8879d7fa9766e58645c3fd8b7a33892a6:{"num_visits":2}'
>>> import json
>>> data = json.loads(x[41:])
>>> print(data)
{'num_visits': 2}
...