Spec-Zone.ru › Django 1.9

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

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

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

Сессии реализуются с помощью средства промежуточного ПО.

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

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

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

Настройка движка сессий

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

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

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

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

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

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

Чтобы хранить данные сессий с помощью системы кэширования Django, вам сначала необходимо убедиться, что ваш кэш настроен; см. документацию по кэшированию для получения подробной информации.

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

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

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

После настройки кэша у вас есть два варианта хранения данных в кэше:

  • Установите SESSION_ENGINE на "django.contrib.sessions.backends.cache" для простого кэшированного хранилища сессий. Данные сессии будут храниться непосредственно в кэше. Однако данные сессии могут не быть постоянными: кэшированные данные могут быть удалены, если кэш заполнится или если сервер кэша перезапустится.
  • Для постоянных кэшированных данных установите SESSION_ENGINE на "django.contrib.sessions.backends.cached_db". Это использует кэш с прохождением записи — каждая запись в кэш также записывается в базу данных. Чтение сессий использует только базу данных, если данные еще не находятся в кэше.

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

Если вы используете бекенд сессий cached_db, вам также необходимо следовать инструкциям по настройке для использования сессий, поддерживаемых базой данных.

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

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

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

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

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

Примечание

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

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

Если SECRET_KEY не хранится в секрете, и вы используете PickleSerializer, это может привести к произвольному выполнению удаленного кода.

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

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

Данные сессии подписываются, но не шифруются

При использовании бекенда куки-файлов клиент может прочитать данные сессии.

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

Нет гарантии свежести

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

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

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

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

Когда 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() вызывает её).

Удаление cookie сессии — это поведение, новое в Django 1.8. Ранее поведение заключалось в перегенерации значения ключа сессии, которое отправлялось обратно пользователю в cookie.

set_test_cookie()

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

test_cookie_worked()

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

delete_test_cookie()

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

set_expiry(value)

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

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

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

get_expiry_age()

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

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

  • modification: последняя модификация сессии в виде объекта datetime. По умолчанию текущее время.
  • expiry: информация об истечении срока действия сессии в виде объекта datetime, целого числа (в секундах) или None. По умолчанию значение, хранящееся в сессии с помощью set_expiry(), если оно есть, или None.
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 известен злоумышленнику (нет встроенной уязвимости в 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 станет известен злоумышленнику.

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

Обратите внимание, что в отличие от PickleSerializer, JSONSerializer не может обрабатывать произвольные типы данных Python. Как часто бывает, существует компромисс между удобством и безопасностью. Если вы хотите хранить более сложные типы данных, включая datetime и Decimal в сессиях на основе JSON, вам необходимо написать пользовательский сериализатор (или преобразовать такие значения в сериализуемые в JSON объекты перед их хранением в request.session). Хотя сериализация этих значений довольно проста (django.core.serializers.json.DateTimeAwareJSONEncoder может быть полезным), написание декодера, который может надежно вернуть то же самое, что вы ввели, более хрупкое. Например, вы рискуете вернуть 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.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_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 или любой сериализуемый объект Python при использовании PickleSerializer. См. модуль pickle для получения дополнительной информации.
  • Данные сессии хранятся в таблице базы данных с именем 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(SessionStore, self).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, вы должны переопределить префикс ключа кэша, чтобы избежать конфликта имён:

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

    # ...

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

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

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

Spec-Zone.ru

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