Недавно возникла необходимость сделать простую вещь – функциональность «запомнить меня». Требования простые: при установленном флажке «запомнить» пользователь считается прошедшим авторизацию и не должен вводить пароль еще раз. Выход из системы в этом случае производится при нажатии кнопки/ссылки «выйти».
При попытке найти что-то готовое результат был курьезный: кто-то решает это путем установки времени истечения сессии в 2036–2039 годах, другие примеры просто неправильные (по всей видимости, написаны под старые версии Django). Пришлось писать решение самому.
Если ваш сайт использует сессии, то механизм «запомнить меня» довольно простой: после успешного прохождения авторизации нужно, используя метод сессии set_expiry, указать, до какого момента будет действительна данная сессия. К сожалению (или к счастью), бесконечно она действительна быть не может, поэтому вы должны либо ее обновлять время от времени, либо просто поставить срок истечения, равный времени, когда вы планируете сменить работу, плюс еще пару лет, чтобы уж наверняка это стало чужой проблемой.
Я решил задачу, написав очень простой и понятный middleware:
from django.conf import settings
from datetime import timedelta, date
class KeepLoggedInMiddleware(object):
def process_request(self, request):
if not request.user.is_authenticated() or not settings.KEEP_LOGGED_KEY in request.session:
return
if request.session[settings.KEEP_LOGGED_KEY] != date.today():
request.session.set_expiry(timedelta(days=settings.KEEP_LOGGED_DURATION))
request.session[settings.KEEP_LOGGED_KEY] = date.today()
return
Чем удобен middleware: не требуется никакой дополнительный код где-то еще. Для работы в Settings нужно сделать следующее:
- Добавить имя_модуля. KeepLoggedInMiddleware в MIDDLEWARE_CLASSES (я поставил его последним, чтобы уже работал middleware сессий)
- Добавить настройки:
# Keep me logged settings
KEEP_LOGGED_KEY = 'keep_me_logged'
KEEP_LOGGED_DURATION = 365 # in days
KEEP_LOGGED_KEY – имя ключа с данными в сессии пользователя, KEEP_LOGGED_DURATION – срок в днях, который вы бы хотели помнить пользователя. Одного года, на мой взгляд, более чем достаточно.
Затем в функции обработки формы авторизации, если флажок «запомнить меня» включен, вы делаете примерно следующее:
form = LoginForm(request.POST)
if form.is_valid():
....
if form.remember:
request.session[settings.KEEP_LOGGED_KEY] = True
После чего при обработке любого запроса middleware увидит, что настройка включена, а обновление не случилось, и обновит дату в сессии. Чаще чем раз в день, на мой взгляд, этого делать не нужно.
Можно не хранить дату последнего обновления, а просто проверять, когда истечет текущая сессия, и продлевать ее – правда, количество кода при этом не изменится, так что это дело вкуса.
При выходе из системы (logout) Django автоматически почистит все данные сессии, т. е. никаких дополнительных действий не требуется.
