Как истечь сеанс из-за бездействия в Django?
В нашем приложении Django есть следующие требования к управлению сеансом.
- Сессии истекают, когда пользователь закрывает браузер.
- Сессии истекают после периода бездействия.
- Обнаружение, когда сеанс истекает из-за неактивности и отображает соответствующее сообщение пользователю.
- Предупреждать пользователей о предстоящем завершении сеанса за несколько минут до окончания периода бездействия. Наряду с предупреждением, предоставить пользователям возможность продлить сеанс.
- Если пользователь работает с длинной деловой активностью в приложении, которая не включает запросы, отправляемые на сервер, сеанс не должен истекать.
После прочтения документации, кода Django и некоторых сообщений в блоге, связанных с этим, я придумал следующий подход к реализации.
Требование 1
Это требование легко реализовать, установив для параметра SESSION_EXPIRE_AT_BROWSER_CLOSE значение True.
Требование 2
Я видел несколько рекомендаций по использованию SESSION_COOKIE_AGE для установки периода истечения срока действия сеанса. Но этот метод имеет следующие проблемы.
-
Сессия всегда заканчивается в конце SESSION_COOKIE_AGE, даже если пользователь активно использует приложение. (Этого можно предотвратить, установив время окончания сеанса на SESSION_COOKIE_AGE для каждого запроса с использованием специального промежуточного программного обеспечения или путем сохранения сеанса для каждого запроса, установив для параметра SESSION_SAVE_EVERY_REQUEST значение true. Но следующая проблема неизбежна из-за использования SESSION_COOKIE_AGE.)
-
Из-за того, как файлы cookie работают, SESSION_EXPIRE_AT_BROWSER_CLOSE и SESSION_COOKIE_AGE являются взаимоисключающими, т.е. файл cookie либо истекает, либо закрывается браузером или в указанное время истечения срока действия. Если используется SESSION_COOKIE_AGE, и пользователь закрывает браузер до истечения срока действия файла cookie, файл cookie сохраняется и повторное открытие браузера позволяет пользователю (или кому-либо еще) войти в систему без повторной аутентификации.
-
Django полагается только на присутствующий файл cookie, чтобы определить, активен ли сеанс. Он не проверяет дату окончания сеанса, хранящуюся в сеансе.
Для реализации этого требования и использования описанных выше проблем можно использовать следующий метод.
- Не устанавливайте SESSION_COOKIE_AGE.
- Установите дату истечения срока действия сеанса как "текущее время + период бездействия" для каждого запроса.
- Переопределите process_request в SessionMiddleware и проверьте срок действия сеанса. Отмените сеанс, если он истек.
Требование 3
Когда мы обнаруживаем, что сеанс истек (в пользовательском SessionMiddleware выше), установите атрибут в запросе, чтобы указать истечение сеанса. Этот атрибут может использоваться для отображения соответствующего сообщения пользователю.
Требование 4
Используйте JavaScript, чтобы обнаружить неактивность пользователя, предоставьте предупреждение, а также возможность продлить сеанс. Если пользователь хочет продлить действие, отправьте на сервер продолж. Импульс, чтобы продлить сеанс.
Требование 5
Используйте JavaScript для определения активности пользователя (во время длительной бизнес-операции) и отправки оставшихся импульсов на сервер, чтобы не допустить завершения сеанса.
Вышеупомянутый подход к внедрению кажется очень сложным, и мне было интересно, может ли быть более простой метод (особенно для требования 2).
Любые идеи будут высоко оценены.
Ответы
Ответ 1
Вот идея... Завершите сеанс в браузере рядом с настройкой SESSION_EXPIRE_AT_BROWSER_CLOSE
. Затем установите временную метку в сеансе для каждого запроса, например:
request.session['last_activity'] = datetime.now()
и добавьте промежуточное программное обеспечение, чтобы определить, закончился ли сеанс. что-то вроде этого должно обрабатывать весь процесс...
from datetime import datetime
from django.http import HttpResponseRedirect
class SessionExpiredMiddleware:
def process_request(request):
last_activity = request.session['last_activity']
now = datetime.now()
if (now - last_activity).minutes > 10:
# Do logout / expire session
# and then...
return HttpResponseRedirect("LOGIN_PAGE_URL")
if not request.is_ajax():
# don't set this for ajax requests or else your
# expired session checks will keep the session from
# expiring :)
request.session['last_activity'] = now
Затем вам просто нужно сделать некоторые URL-адреса и представления, чтобы вернуть соответствующие данные в вызовы ajax в отношении истечения срока действия сеанса.
когда пользователь выбирает "возобновить" сеанс, так сказать, все, что вам нужно сделать, это установить requeset.session['last_activity']
на текущее время снова
Очевидно, что этот код является только началом... но он должен получить вас на правильном пути
Ответ 2
django-session-security делает именно это...
... с дополнительным требованием: если сервер не отвечает или злоумышленник отключил интернет-соединение: он должен истечь в любом случае.
Disclamer: Я поддерживаю это приложение. Но я смотрел эту тему очень и очень долго:)
Ответ 3
Я просто совершенно новый, чтобы использовать Django.
Я хотел сделать сеанс завершенным, если зарегистрированный пользователь закроет браузер или находится в режиме ожидания (время бездействия) на некоторое время. Когда я разобрался в Google, этот вопрос SOF возник первым. Благодаря приятному ответу я искал ресурсы, чтобы понять, как работает middlewares во время цикла запросов/ответов в Django. Это было очень полезно.
Я собирался применить специальное промежуточное программное обеспечение в свой код, следуя главному ответу здесь. Но я все еще немного подозрительно, потому что лучший ответ здесь был отредактирован в 2011 году. Я потратил больше времени, чтобы немного поискать результат недавнего поиска и придумал простой способ.
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_COOKIE_AGE = 10 # set just 10 seconds to test
SESSION_SAVE_EVERY_REQUEST = True
Я не проверял другие браузеры, но хром.
1. Сессия закончилась, когда я закрыл браузер, даже если установлен SESSION_COOKIE_AGE.
2. Только когда я простаивал более 10 секунд, сеанс истек. Благодаря SESSION_SAVE_EVERY_REQUEST, всякий раз, когда вы выполняете новый запрос, он сохраняет сеанс и время ожидания обновлений до истечения срока действия
Чтобы изменить это поведение по умолчанию, установите для параметра SESSION_SAVE_EVERY_REQUEST значение True. Если установлено значение True, Django будет сохранять сеанс в базе данных при каждом отдельном запросе.
Обратите внимание, что cookie сеанса отправляется только тогда, когда сеанс был создан или изменен. Если SESSION_SAVE_EVERY_REQUEST имеет значение True, cookie сеанса будет отправляться по каждому запросу.
Аналогично, истекшая часть куки файла сеанса обновляется каждый раз, когда отправляется куки файл сеанса.
руководство django 1.10
Я просто оставляю ответ так, что некоторые люди, которые являются чем-то новым в Django, как я, не тратят много времени, чтобы найти решение так, как я сделал.
Ответ 4
Одним из простых способов удовлетворить ваше второе требование было бы установить значение SESSION_COOKIE_AGE в settings.py на подходящее количество секунд. Например:
SESSION_COOKIE_AGE = 600 #10 minutes.
Однако, только делая это, сеанс истечет через 10 минут независимо от того, демонстрирует ли пользователь какую-либо активность. Чтобы справиться с этой проблемой, срок действия может быть автоматически возобновлен (еще на дополнительные 10 минут) каждый раз, когда пользователь выполняет любой запрос со следующим предложением:
request.session.set_expiry(request.session.get_expiry_age())
Ответ 5
также вы можете использовать
fooobar.com/questions/79133/...
SESSION_SAVE_EVERY_REQUEST = True
Ответ 6
В первом запросе вы можете установить истечение сеанса как
self.request.session['access_key'] = access_key
self.request.session['access_token'] = access_token
self.request.session.set_expiry(set_age) #in seconds
И при использовании access_key и токена
try:
key = self.request.session['access_key']
except KeyError:
age = self.request.session.get_expiry_age()
if age > set_age:
#redirect to login page