Spec-Zone.ru › Django 4.2

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

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

Включение сессий

Сессии реализованы с помощью фрагмента средства.

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

  • Отредактируйте параметр 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, вам сначала необходимо убедиться, что вы настроила ваш кэш; см. документацию по кэшу для получения подробностей.

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

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

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

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

Кэшированное хранилище базы данных (cached_db) использует проходной кэш — записи сессий применяются как к кэшу, так и к базе данных. Чтения сессий используют кэш, или базу данных, если данные были удалены из кэша. Чтобы использовать это хранилище, установите SESSION_ENGINE на "django.contrib.sessions.backends.cached_db", и следуйте инструкциям по настройке для использования сессий, поддерживаемых базой данных.

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

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

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

Для использования сессий на основе файлов установите параметр SESSION_ENGINE на "django.contrib.sessions.backends.file".

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

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

Для использования сессий на основе файлов cookie установите параметр SESSION_ENGINE на "django.contrib.sessions.backends.signed_cookies". Данные сессий будут храниться с помощью инструментов Django для криптографического шифрования и параметра SECRET_KEY.

Примечание

Рекомендуется оставлять параметр SESSION_COOKIE_HTTPONLY в значении True для предотвращения доступа к хранящимся данным из JavaScript.

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

Если SECRET_KEY или SECRET_KEY_FALLBACKS не являются секретными, и вы используете django.contrib.sessions.serializers.PickleSerializer, это может привести к произвольному удалённому выполнению кода.

Злоумышленник, получивший доступ к SECRET_KEY или SECRET_KEY_FALLBACKS, может не только сгенерировать поддельные данные сессий, которым доверяет ваш сайт, но также выполнить произвольный удалённый код, поскольку данные сериализуются с помощью pickle.

Если вы используете сессии на основе cookie, позаботьтесь о том, чтобы ваш секретный ключ всегда оставался совершенно секретным для любого удалённо доступного компонента.

Данные сессии подписаны, но не зашифрованы

При использовании cookie-хранилища клиент может прочитать данные сессий.

MAC (Message Authentication Code) используется для защиты данных от изменений клиентом, поэтому данные сессии будут аннулированы при попытке взлома. То же самое происходит, если клиент, хранящий cookie (например, браузер вашего пользователя), не может сохранить все cookie сессии и теряет данные. Несмотря на то, что Django сжимает данные, вполне возможно превысить обычное ограничение в 4096 байт на cookie.

Гарантия актуальности отсутствует

Обратите также внимание, что, хотя MAC может гарантировать подлинность данных (что они были сгенерированы вашим сайтом, а не кем-то другим) и целостность данных (что они все там и верны), он не может гарантировать актуальность, т.е. что вам возвращается последняя отправленная данным сессии. Это означает, что для некоторых применений данных сессий cookie-хранилище может сделать вас уязвимым для атак с повторением. В отличие от других хранилищ сессий, которые сохраняют запись каждой сессии на сервере и аннулируют её при выходе пользователя, сессии на основе cookie не аннулируются при выходе пользователя. Таким образом, если злоумышленник украдёт cookie пользователя, он может использовать этот cookie для входа как этот пользователь, даже если пользователь уже вышел. Cookie будет считаться «старым» только если он старше, чем ваш SESSION_COOKIE_AGE.

Производительность

Наконец, размер cookie может повлиять на скорость вашего сайта.

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

Когда 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()

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

set_test_cookie()

Устанавливает тестовое cookie для определения возможности поддержки cookie браузером пользователя. Из-за работы cookie вы не сможете проверить это до следующего запроса страницы пользователя. Дополнительную информацию см. в разделе «Настройка тестовых cookie» ниже.

test_cookie_worked()

Возвращает либо True или False, в зависимости от того, принял ли браузер пользователя тестовое cookie. Из-за работы cookie вам придется вызвать set_test_cookie() на предыдущем отдельном запросе страницы. Дополнительную информацию см. в разделе «Настройка тестовых cookie» ниже.

delete_test_cookie()

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

get_session_cookie_age()

Возвращает значение настройки 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, целого числа (в секундах) или 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 для сериализации данных сессии. Если вы используете бэкенд подписанных cookie сессий и 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, такие как байты, не являющиеся UTF-8, например, '\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, который на самом деле был строкой, которая просто оказалась в том же формате, который был выбран для datetime.

Ваш класс сериализатора должен реализовывать два метода, 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 предоставляет способ проверки того, принимает ли браузер пользователя файлы cookie. Вызовите метод set_test_cookie() объекта request.session в представлении и вызовите test_cookie_worked() в последующем представлении – не в том же вызове представления.

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

Рекомендуется использовать delete_test_cookie(), чтобы очистить за собой. Сделайте это после того, как вы проверили, что тестовый файл 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, что означает, что файлы cookie сессий будут храниться в браузерах пользователей до истечения срока действия SESSION_COOKIE_AGE. Используйте это значение, если вы не хотите, чтобы пользователи каждый раз входили в систему при открытии браузера.

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

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

Примечание

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

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

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

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

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

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

Настройки

Несколько настроек Django позволяют контролировать поведение сессий:

  • SESSION_CACHE_ALIAS
  • SESSION_COOKIE_AGE
  • SESSION_COOKIE_DOMAIN
  • SESSION_COOKIE_HTTPONLY
  • SESSION_COOKIE_NAME
  • SESSION_COOKIE_PATH
  • SESSION_COOKIE_SAMESITE
  • SESSION_COOKIE_SECURE
  • SESSION_ENGINE
  • SESSION_EXPIRE_AT_BROWSER_CLOSE
  • SESSION_FILE_PATH
  • SESSION_SAVE_EVERY_REQUEST
  • SESSION_SERIALIZER

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

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

Например, злоумышленник может войти в good.example.com и получить действительную сессию для своей учётной записи. Если злоумышленник контролирует bad.example.com, он может использовать его для отправки ключа сессии, так как поддомен разрешено устанавливать куки на *.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 используется объект хранилища сессий из соответствующего движка сессий. По соглашению, класс объекта хранилища сессий называется SessionStore и находится в модуле, определённом SESSION_ENGINE.

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

  • exists()
  • create()
  • save()
  • delete()
  • load()
  • clear_expired()

Для создания пользовательского движка сессий или для настройки существующего можно создать новый класс, унаследованный от 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 полностью и только основана на куки. Она не использует URL для хранения идентификаторов сессии в качестве последней меры, в отличие от PHP. Это преднамеренное конструкторское решение. Такое поведение не только делает URL неприглядными, но и делает ваш сайт уязвимым к краже идентификаторов сессий через заголовок «Referer».

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/4.2/topics/http/sessions/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API