Как использовать сеансы

Django обеспечивает полную поддержку анонимных сессий. Фреймворк сессий позволяет хранить и извлекать произвольные данные для каждого посетителя сайта. Он хранит данные на стороне сервера и абстрагирует отправку и получение cookies. Cookies содержат идентификатор сессии, а не сами данные (если только вы не используете cookie based backend).

Разрешение сеансов

Сессии реализуются через кусок middleware.

Чтобы включить функцию сеанса, сделайте следующее:

  • Отредактируйте параметр MIDDLEWARE и убедитесь, что он содержит 'django.contrib.sessions.middleware.SessionMiddleware'. По умолчанию settings.py, созданный django-admin startproject, активирован SessionMiddleware.

Если вы не хотите использовать сессии, вы также можете удалить строку SessionMiddleware из MIDDLEWARE и 'django.contrib.sessions' из INSTALLED_APPS. Это сэкономит вам немного накладных расходов.

Настройка механизма сеансов

По умолчанию Django хранит сессии в вашей базе данных (используя модель django.contrib.sessions.models.Session). Хотя это удобно, в некоторых случаях быстрее хранить данные сессии в другом месте, поэтому Django может быть настроен на хранение данных сессии в вашей файловой системе или в вашем кэше.

Использование сеансов с поддержкой базы данных

Если вы хотите использовать сессию с опорой на базу данных, вам нужно добавить 'django.contrib.sessions' к настройке INSTALLED_APPS.

После настройки установки выполните команду manage.py migrate для установки единственной таблицы базы данных, в которой хранятся данные сеанса.

Использование кэшированных сессий

Для повышения производительности вы можете использовать бэкэнд сессий на основе кэша.

Чтобы хранить данные сессии, используя систему кэширования Django, вам сначала нужно убедиться, что вы настроили свой кэш; подробности см. в cache documentation.

Предупреждение

Сеансы на основе кэша следует использовать только в том случае, если вы используете бэкенд кэша Memcached или Redis. Бэкенд кэша локальной памяти не хранит данные достаточно долго, чтобы быть хорошим выбором, и будет быстрее использовать сессии файлов или баз данных напрямую вместо того, чтобы отправлять все через бэкенды кэша файлов или баз данных. Кроме того, бэкенд кэша локальной памяти НЕ является многопроцессным, поэтому, вероятно, не является хорошим выбором для производственных сред.

Если у вас несколько кэшей, определенных в CACHES, Django будет использовать кэш по умолчанию. Чтобы использовать другой кэш, задайте в SESSION_CACHE_ALIAS имя этого кэша.

Once your cache is configured, you have to choose between a database-backed cache or a non-persistent cache.

Бэкэнд базы данных с кэшем (cached_db) использует сквозной кэш - записи сессий применяются как к кэшу, так и к базе данных. Сессионные чтения используют кэш или базу данных, если данные были удалены из кэша. Чтобы использовать этот бэкэнд, установите SESSION_ENGINE в "django.contrib.sessions.backends.cached_db" и следуйте инструкциям по настройке using database-backed sessions.

Бэкэнд кэша (cache) хранит данные сессии только в вашем кэше. Это быстрее, поскольку позволяет избежать персистентности базы данных, но вам придется подумать о том, что произойдет, когда данные кэша будут вытеснены. Выселение может произойти, если кэш заполнится или сервер кэша будет перезапущен, и это будет означать потерю данных сессии, включая выход пользователей из системы. Чтобы использовать этот бэкенд, установите SESSION_ENGINE на "django.contrib.sessions.backends.cache".

Бэкэнд кэша можно сделать постоянным, используя постоянный кэш, например, Redis с соответствующей конфигурацией. Но если ваш кэш не настроен на достаточную стойкость, выбирайте бэкэнд базы данных с кэшем. Это позволит избежать побочных ситуаций, вызванных ненадежным хранением данных в производстве.

Использование сеансов на основе файлов

Чтобы использовать сессии на основе файлов, установите параметр SESSION_ENGINE в значение "django.contrib.sessions.backends.file".

Возможно, вы также захотите установить параметр SESSION_FILE_PATH (который по умолчанию выводится из tempfile.gettempdir(), скорее всего, /tmp), чтобы контролировать, где Django хранит файлы сессий. Обязательно проверьте, что ваш веб-сервер имеет права на чтение и запись в это место.

Использование сессий в представлениях

Когда SessionMiddleware активирован, каждый объект HttpRequest - первый аргумент любой функции представления Django - будет иметь атрибут session, который является словареподобным объектом.

Вы можете читать его и записывать в request.session в любой точке вашего представления. Вы можете редактировать его несколько раз.

class backends.base.SessionBase

Это базовый класс для всех объектов сессии. Он имеет следующие стандартные методы словаря:

__getitem__(key)

Пример: fav_color = request.session['fav_color']

__setitem__(key, value)

Пример: request.session['fav_color'] = 'blue'

__delitem__(key)

Пример: del request.session['fav_color']. Это поднимает KeyError, если данный key еще не находится в сессии.

__contains__(key)

Пример: 'fav_color' in request.session

get(key, default=None)

Пример: fav_color = request.session.get('fav_color', 'red')

pop(key, default=__not_given)

Пример: fav_color = request.session.pop('fav_color', 'blue')

keys()
items()
setdefault()
clear()

Он также имеет такие методы:

flush()

Удаляет данные текущей сессии и удаляет куки сессии. Это используется, если вы хотите, чтобы данные предыдущей сессии не могли быть снова доступны из браузера пользователя (например, функция django.contrib.auth.logout() вызывает ее).

Устанавливает тестовый файл cookie, чтобы определить, поддерживает ли браузер пользователя файлы cookie. В связи с тем, как работают куки, вы не сможете проверить это до следующего запроса страницы пользователем. Дополнительную информацию см. в разделе Setting test cookies ниже.

Возвращает либо True, либо False, в зависимости от того, принял ли браузер пользователя тестовый файл cookie. В связи с тем, как работают куки, вам придется вызвать set_test_cookie() на предыдущем, отдельном запросе страницы. См. раздел Setting test cookies ниже для получения дополнительной информации.

Удаляет тестовый файл cookie. Используйте это, чтобы убрать за собой.

Возвращает значение параметра SESSION_COOKIE_AGE. Это значение может быть переопределено в пользовательском бэкенде сессии.

set_expiry(value)

Устанавливает время истечения срока действия сессии. Вы можете передать несколько различных значений:

  • Если value - целое число, то сессия завершится через столько-то секунд бездействия. Например, вызов request.session.set_expiry(300) приведет к тому, что сессия завершится через 5 минут.
  • Если value является объектом datetime или timedelta, то сессия истечет в определенную дату/время.
  • Если value равно 0, срок действия cookie сессии пользователя истекает после закрытия веб-браузера пользователя.
  • Если value равно None, сессия возвращается к использованию глобальной политики истечения срока действия сессии.

Чтение сессии не считается активностью для целей истечения срока действия. Срок действия сессии отсчитывается от последнего времени, когда сессия была изменена.

get_expiry_age()

Возвращает количество секунд до истечения срока действия данной сессии. Для сессий без пользовательского срока действия (или настроенных на истечение при закрытии браузера) это значение будет равно SESSION_COOKIE_AGE.

Эта функция принимает два необязательных аргумента в виде ключевых слов:

  • modification: последняя модификация сессии, как объект datetime. По умолчанию - текущее время.
  • expiry: информация об истечении срока действия сессии, в виде объекта datetime, int (в секундах) или None. По умолчанию используется значение, сохраненное в сессии по set_expiry(), если оно есть, или None.

Примечание

Этот метод используется бэкендами сессий для определения срока действия сессии в секундах при сохранении сессии. Он не предназначен для использования вне этого контекста.

В частности, хотя возможно определить оставшееся время жизни сессии только тогда, когда у вас есть правильное значение modification **и expiry установлен как объект datetime, когда у вас есть значение modification, более просто рассчитать срок действия вручную:

expires_at = modification + timedelta(seconds=settings.SESSION_COOKIE_AGE)
get_expiry_date()

Возвращает дату истечения срока действия этой сессии. Для сессий без пользовательского срока действия (или настроенных на истечение срока действия при закрытии браузера) эта дата будет равна SESSION_COOKIE_AGE секунд от настоящего момента.

Эта функция принимает те же аргументы ключевых слов, что и get_expiry_age(), и к ней применимы аналогичные указания по использованию.

get_expire_at_browser_close()

Возвращает либо True, либо False, в зависимости от того, истечет ли срок действия cookie сессии пользователя при закрытии веб-браузера пользователя.

clear_expired()

Удаляет истекшие сессии из хранилища сессий. Этот метод класса вызывается командой clearsessions.

cycle_key()

Создает новый ключ сессии, сохраняя текущие данные сессии. django.contrib.auth.login() вызывает этот метод для защиты от фиксации сеанса.

Сериализация сеанса

По умолчанию Django сериализует данные сессии, используя JSON. Вы можете использовать параметр SESSION_SERIALIZER для настройки формата сериализации сессии. Даже с учетом предостережений, описанных в Напишите свой собственный сериализатор, мы настоятельно рекомендуем придерживаться сериализации JSON особенно если вы используете бэкенд cookie.

Например, вот сценарий атаки, если вы используете pickle для сериализации данных сессии. Если вы используете signed cookie session backend и SECRET_KEY (или любой ключ из SECRET_KEY_FALLBACKS) известен злоумышленнику (в Django нет врожденной уязвимости, которая привела бы к его утечке), то злоумышленник может вставить в сессию строку, которая, будучи распакованной, выполнит произвольный код на сервере. Техника для этого проста и легко доступна в интернете. Хотя хранилище сессий cookie подписывает данные, хранящиеся в cookie, чтобы предотвратить подделку, утечка SECRET_KEY немедленно перерастает в уязвимость удаленного выполнения кода.

Сериализаторы в комплекте

class serializers.JSONSerializer

Обертка вокруг сериализатора JSON из django.core.signing. Может сериализовать только основные типы данных.

Кроме того, поскольку JSON поддерживает только строковые ключи, обратите внимание, что использование нестроковых ключей в request.session не будет работать так, как ожидалось:

>>> # initial assignment
>>> request.session[0] = 'bar'
>>> # subsequent requests following serialization & deserialization
>>> # of session data
>>> request.session[0]  # KeyError
>>> request.session['0']
'bar'

Аналогично, данные, которые не могут быть закодированы в JSON, такие как байты, не относящиеся к стандарту UTF8, например '\xd9' (который поднимает UnicodeDecodeError), не могут быть сохранены.

Более подробно об ограничениях сериализации JSON смотрите в разделе Напишите свой собственный сериализатор.

class serializers.PickleSerializer

Поддерживает произвольные объекты Python, но, как описано выше, может привести к уязвимости удаленного выполнения кода, если SECRET_KEY или любой ключ из SECRET_KEY_FALLBACKS станет известен злоумышленнику.

Не рекомендуется, начиная с версии 4.1: Из-за риска удаленного выполнения кода этот сериализатор устарел и будет удален в Django 5.0.

Напишите свой собственный сериализатор

Обратите внимание, что JSONSerializer не может работать с произвольными типами данных Python. Как это часто бывает, существует компромисс между удобством и безопасностью. Если вы хотите хранить более сложные типы данных, включая datetime и Decimal, в сессиях с поддержкой JSON, вам придется написать собственный сериализатор (или преобразовать такие значения в сериализуемый объект JSON перед хранением в request.session). В то время как сериализация этих значений часто проста (может помочь DjangoJSONEncoder), написание декодера, который может надежно получить обратно то же самое, что вы ввели, более хрупко. Например, вы рискуете вернуть datetime, который на самом деле был строкой, которая просто оказалась в том же формате, который был выбран для datetimes).

Ваш класс сериализатора должен реализовать два метода, dumps(self, obj) и loads(self, data), для сериализации и десериализации словаря данных сессии, соответственно.

Рекомендации по объектам сеанса

  • Используйте обычные строки Python в качестве ключей словаря на request.session. Это скорее условность, чем жесткое правило.
  • Ключи словаря сессий, начинающиеся с символа подчеркивания, зарезервированы для внутреннего использования Django.
  • Не переопределяйте request.session с новым объектом, не обращайтесь к его атрибутам и не устанавливайте их. Используйте его как словарь Python.

Примеры

Это упрощенное представление устанавливает переменную has_commented в True после того, как пользователь публикует комментарий. Оно не позволяет пользователю публиковать комментарий более одного раза:

def post_comment(request, new_comment):
    if request.session.get('has_commented', False):
        return HttpResponse("You've already commented.")
    c = comments.Comment(comment=new_comment)
    c.save()
    request.session['has_commented'] = True
    return HttpResponse('Thanks for your comment!')

Это упрощенное представление регистрирует «члена» сайта:

def login(request):
    m = Member.objects.get(username=request.POST['username'])
    if m.check_password(request.POST['password']):
        request.session['member_id'] = m.id
        return HttpResponse("You're logged in.")
    else:
        return HttpResponse("Your username and password didn't match.")

…А этот выводит пользователя из системы, согласно login() выше:

def logout(request):
    try:
        del request.session['member_id']
    except KeyError:
        pass
    return HttpResponse("You're logged out.")

Стандартная функция django.contrib.auth.logout() на самом деле делает немного больше, чем это, чтобы предотвратить непреднамеренную утечку данных. Она вызывает метод flush() из request.session. Мы используем этот пример как демонстрацию работы с объектами сессии, а не как полную реализацию logout().

Установка тестовых файлов cookie

В качестве удобства Django предоставляет способ проверить, принимает ли браузер пользователя cookies. Вызовите метод set_test_cookie() из request.session в представлении и вызовите test_cookie_worked() в последующем представлении - не в том же вызове представления.

Это неудобное разделение между set_test_cookie() и test_cookie_worked() необходимо из-за того, как работают куки. Когда вы устанавливаете cookie, вы не можете сказать, принял ли его браузер, до следующего запроса браузера.

Хорошей практикой является использование delete_test_cookie(), чтобы убрать за собой. Сделайте это после того, как убедитесь, что тестовая печенька сработала.

Вот типичный пример использования:

from django.http import HttpResponse
from django.shortcuts import render

def login(request):
    if request.method == 'POST':
        if request.session.test_cookie_worked():
            request.session.delete_test_cookie()
            return HttpResponse("You're logged in.")
        else:
            return HttpResponse("Please enable cookies and try again.")
    request.session.set_test_cookie()
    return render(request, 'foo/login_form.html')

Использование сеансов из представлений

Примечание

Примеры в этом разделе импортируют объект SessionStore непосредственно из бэкенда django.contrib.sessions.backends.db. В своем собственном коде вы должны рассмотреть возможность импорта SessionStore из механизма сессии, обозначенного SESSION_ENGINE, как показано ниже:

>>> from importlib import import_module
>>> from django.conf import settings
>>> SessionStore = import_module(settings.SESSION_ENGINE).SessionStore

Для работы с данными сессии вне представления существует API:

>>> from django.contrib.sessions.backends.db import SessionStore
>>> s = SessionStore()
>>> # stored as seconds since epoch since datetimes are not serializable in JSON.
>>> s['last_login'] = 1376587691
>>> s.create()
>>> s.session_key
'2b1189a188b44ad18c35e113ac6ceead'
>>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
>>> s['last_login']
1376587691

SessionStore.create() предназначен для создания новой сессии (т.е. сессии, не загруженной из хранилища сессий и с session_key=None). save() предназначен для сохранения существующей сессии (т.е. сессии, загруженной из хранилища сессий). Вызов save() на новой сессии также может сработать, но имеет небольшую вероятность генерации session_key, которая столкнется с существующей сессией. create() вызывает save() и зацикливается, пока не будет сгенерирован неиспользуемый session_key.

Если вы используете бэкенд django.contrib.sessions.backends.db, каждая сессия - это обычная модель Django. Модель Session определена в django/contrib/sessions/models.py. Поскольку это обычная модель, вы можете получить доступ к сессиям, используя обычный API базы данных Django:

>>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)

Обратите внимание, что вам нужно будет вызвать get_decoded(), чтобы получить словарь сессии. Это необходимо, потому что словарь хранится в закодированном формате:

>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
>>> s.get_decoded()
{'user_id': 42}

Когда сохраняются сеансы

По умолчанию Django сохраняет данные в базе данных сессии только в том случае, если сессия была изменена - то есть, если любое из значений ее словаря было присвоено или удалено:

# Session is modified.
request.session['foo'] = 'bar'

# Session is modified.
del request.session['foo']

# Session is modified.
request.session['foo'] = {}

# Gotcha: Session is NOT modified, because this alters
# request.session['foo'] instead of request.session.
request.session['foo']['bar'] = 'baz'

В последнем случае приведенного выше примера мы можем явно сообщить объекту сессии, что он был изменен, установив атрибут modified на объекте сессии:

request.session.modified = True

Чтобы изменить это поведение по умолчанию, установите параметр SESSION_SAVE_EVERY_REQUEST в значение True. Если установить значение True, Django будет сохранять сессию в базе данных при каждом запросе.

Обратите внимание, что сессионный cookie отправляется только тогда, когда сессия была создана или изменена. Если SESSION_SAVE_EVERY_REQUEST равно True, сессионный cookie будет отправляться при каждом запросе.

Аналогично, часть expires сеансового cookie обновляется при каждой отправке сеансового cookie.

Сессия не сохраняется, если код состояния ответа равен 500.

Сеансы длиной в браузер и постоянные сеансы

С помощью параметра SESSION_EXPIRE_AT_BROWSER_CLOSE вы можете контролировать, использует ли фреймворк сессий сеансы длиной в браузер или постоянные сеансы.

По умолчанию значение SESSION_EXPIRE_AT_BROWSER_CLOSE установлено на False, что означает, что сеансовые куки будут храниться в браузерах пользователей до тех пор, пока SESSION_COOKIE_AGE. Используйте это, если вы не хотите, чтобы людям приходилось входить в систему каждый раз, когда они открывают браузер.

Если SESSION_EXPIRE_AT_BROWSER_CLOSE установлено в значение True, Django будет использовать cookies длиной в браузер - cookies, срок действия которых истекает, как только пользователь закрывает браузер. Используйте это, если вы хотите, чтобы людям приходилось входить в систему каждый раз, когда они открывают браузер.

Эта настройка является глобальной по умолчанию и может быть перезаписана на уровне каждой сессии путем явного вызова метода set_expiry() из request.session, как описано выше в using sessions in views.

Примечание

Некоторые браузеры (например, Chrome) предоставляют настройки, позволяющие пользователям продолжать сеансы просмотра после закрытия и повторного открытия браузера. В некоторых случаях это может мешать настройке SESSION_EXPIRE_AT_BROWSER_CLOSE и предотвращать завершение сеансов при закрытии браузера. Пожалуйста, помните об этом при тестировании приложений Django, в которых включена настройка SESSION_EXPIRE_AT_BROWSER_CLOSE.

Очистка хранилища сеансов

По мере того как пользователи создают новые сессии на вашем сайте, данные сессии могут накапливаться в хранилище сессий. Если вы используете бэкенд базы данных, таблица базы данных django_session будет расти. Если вы используете файловый бэкенд, ваш временный каталог будет содержать все большее количество файлов.

Чтобы понять эту проблему, рассмотрим, что происходит с бэкендом базы данных. Когда пользователь входит в систему, Django добавляет строку в таблицу базы данных django_session. Django обновляет эту строку каждый раз, когда данные сессии изменяются. Если пользователь выходит из системы вручную, Django удаляет эту строку. Но если пользователь не вышел из системы, строка никогда не будет удалена. Аналогичный процесс происходит и с файловым бэкендом.

Django не обеспечивает автоматическую очистку истекших сессий. Поэтому ваша работа заключается в регулярной очистке истекших сессий. Django предоставляет для этого команду управления очисткой: clearsessions. Рекомендуется вызывать эту команду на регулярной основе, например, в качестве ежедневного задания cron.

Обратите внимание, что бэкэнд кэша не подвержен этой проблеме, поскольку кэш автоматически удаляет устаревшие данные. Бэкэнд cookie также не подвержен этой проблеме, поскольку данные сессии хранятся в браузерах пользователей.

Безопасность сеанса

Поддомены внутри сайта могут устанавливать cookies на клиенте для всего домена. Это делает фиксацию сеанса возможной, если cookies разрешены с поддоменов, не контролируемых доверенными пользователями.

Например, злоумышленник может войти в good.example.com и получить действительную сессию для своей учетной записи. Если злоумышленник имеет контроль над bad.example.com, он может использовать его для отправки вам ключа сессии, поскольку поддомену разрешено устанавливать cookies на *.example.com. Когда вы посетите good.example.com, вы войдете в систему как злоумышленник и можете случайно ввести свои конфиденциальные личные данные (например, информацию о кредитной карте) в аккаунт злоумышленника.

Другой возможной атакой будет, если good.example.com установит свой SESSION_COOKIE_DOMAIN на "example.com", что приведет к отправке сессионных cookie с этого сайта на bad.example.com.

Технические детали

  • Словарь сессии принимает любое сериализуемое значение json при использовании JSONSerializer.
  • Данные сессии хранятся в таблице базы данных с именем django_session .
  • Django отправляет cookie только в том случае, если это необходимо. Если вы не задаете никаких данных сессии, он не будет отправлять сессионный cookie.

Объект SessionStore

При внутренней работе с сессиями Django использует объект session store из соответствующего движка сессий. По соглашению, класс объекта хранилища сессий называется SessionStore и находится в модуле, обозначенном SESSION_ENGINE.

Все классы SessionStore, доступные в Django, наследуются от SessionBase и реализуют методы манипулирования данными, а именно:

Для того чтобы создать пользовательский механизм сессий или адаптировать существующий, вы можете создать новый класс, наследующий от SessionBase или любого другого существующего класса SessionStore.

Вы можете расширить сеансовые движки, но для этого при использовании сеансовых движков с поддержкой базы данных обычно требуются дополнительные усилия (подробности см. в следующем разделе).

Расширение сеансовых движков с опорой на базу данных

Создание собственного механизма сессий с поддержкой базы данных на основе тех, которые включены в Django (а именно db и cached_db) может быть сделано путем наследования AbstractBaseSession и одного из классов SessionStore.

AbstractBaseSession и BaseSessionManager импортируются из django.contrib.sessions.base_session так, что их можно импортировать, не включая django.contrib.sessions в INSTALLED_APPS.

class base_session.AbstractBaseSession

Абстрактная базовая модель сеанса.

session_key

Первичный ключ. Само поле может содержать до 40 символов. Текущая реализация генерирует 32-символьную строку (случайная последовательность цифр и строчных букв ASCII).

session_data

Строка, содержащая закодированный и сериализованный словарь сессии.

expire_date

Время, обозначающее дату окончания сеанса.

Просроченные сессии недоступны пользователю, однако они могут сохраняться в базе данных до тех пор, пока не будет выполнена команда управления clearsessions.

classmethod get_session_store_class()

Возвращает класс хранилища сессии, который будет использоваться с данной моделью сессии.

get_decoded()

Возвращает декодированные данные сессии.

Декодирование выполняется классом хранилища сессий.

Вы также можете настроить менеджер моделей, создав подкласс BaseSessionManager:

class base_session.BaseSessionManager
encode(session_dict)

Возвращает заданный словарь сессии, сериализованный и закодированный в виде строки.

Кодирование выполняется классом хранилища сессий, привязанным к классу модели.

save(session_key, session_dict, expire_date)

Сохраняет данные сессии для предоставленного ключа сессии или удаляет сессию, если данные пусты.

Настройка классов SessionStore достигается путем переопределения методов и свойств, описанных ниже:

class backends.db.SessionStore

Реализует хранение сессий с опорой на базу данных.

classmethod get_model_class()

Переопределите этот метод, чтобы вернуть пользовательскую модель сессии, если она вам нужна.

create_model_instance(data)

Возвращает новый экземпляр объекта модели сессии, который представляет текущее состояние сессии.

Переопределение этого метода дает возможность изменять данные модели сессии до их сохранения в базе данных.

class backends.cached_db.SessionStore

Реализует кэшированное хранилище сессий на основе базы данных.

cache_key_prefix

Префикс, добавляемый к ключу сессии для построения строки ключа кэша.

Пример

В приведенном ниже примере показан пользовательский механизм сессий на основе базы данных, который включает дополнительный столбец базы данных для хранения идентификатора учетной записи (таким образом обеспечивая возможность запроса базы данных для всех активных сессий для учетной записи):

from django.contrib.sessions.backends.db import SessionStore as DBStore
from django.contrib.sessions.base_session import AbstractBaseSession
from django.db import models

class CustomSession(AbstractBaseSession):
    account_id = models.IntegerField(null=True, db_index=True)

    @classmethod
    def get_session_store_class(cls):
        return SessionStore

class SessionStore(DBStore):
    @classmethod
    def get_model_class(cls):
        return CustomSession

    def create_model_instance(self, data):
        obj = super().create_model_instance(data)
        try:
            account_id = int(data.get('_auth_user_id'))
        except (ValueError, TypeError):
            account_id = None
        obj.account_id = account_id
        return obj

Если вы переходите со встроенного в Django хранилища сессий cached_db на пользовательское, основанное на cached_db, вам следует переопределить префикс ключа кэша, чтобы предотвратить столкновение пространств имен:

class SessionStore(CachedDBStore):
    cache_key_prefix = 'mysessions.custom_cached_db_backend'

    # ...

Идентификаторы сессий в URL-адресах

Фреймворк сессий Django полностью и исключительно основан на cookie. Он не возвращается к помещению идентификаторов сессий в URL в качестве последнего средства, как это делает PHP. Это намеренное дизайнерское решение. Такое поведение не только делает URL уродливыми, но и делает ваш сайт уязвимым для кражи идентификатора сессии через заголовок «Referer».

Вернуться на верх