Доброго времени суток! Как принудительно сделать logout для пользователя в flask если этот же пользователь авторизуется через другое устройство? Используется библиотека flask-login, также есть версия с flask-httpauth
@app.before_request
def before_request():
user_id = session.get('user_id', None)
# Дальше проверяем, есть ли у user_id другие открытые сессии.
# Если сессия есть, то
# session.clear()
Radist_101: Если сессии хранятся на сервере, то обратится к серверу и проверить.
Например, обратится к MySQL, sqlite, текстовые файлы и т.д.
А вот если сессии хранятся в куках пользователя, тогда два пути. Или переходить на серверное хранение или написать что-нибудь самописное. И хранить имя сессии и user_id в виде словаря, где-нибудь на сервере и обращаться при необходимости. В redis хорошо такие вещи держать, в формате ключ - значение.
pcdesign: для редиса нашел такой сниппет flask.pocoo.org/snippets/75 , допустим я очищаю сессию таким образом session.clear(), это же я очищаю сессию только для текущего пользователя, который авторизован или я что то не понимаю
Radist_101: А по идеи с этим снипетом заработает session_protection == 'strong'.
flask-login сам будет уже проверять и before_request будет не нужен.
before_request - пригодился бы, если вы захотите сами написать проверку.
Ну то есть обратились к базе редиски. И проверили сколько открытых сессий у юзера, если больше одной то их бы отстрелили.
Radist_101: Вы можете хранить сессии в MySQL. Возможно, вам будет удобнее. Зайдете и сделаете выборку. А когда с MySQL разберетесь, то можно будет перенести в редис, да и то если будет тормозить.
А если будет работать быстро, то с редисом можно не заморачиваться.
pcdesign: Я просто не до конца понимаю, если я буду хранить сессию в базе, например используя pythonhosted.org/Flask-Session, то как завершать сессию любого пользователя, вызов session.clear() очистит же сессию только для текущего пользователя,
Radist_101: Надо запросить у базы все сессии данного юзера.
И удалить их тоже.
Типа, "'DELETE FROM session WHERE '".
После этого все сессии, на всех устройствах у юзера станут недействительны.
session.clear() - не обязательно.
Можно просто просто заредиректить на /logout/ - текущего юзера.
pcdesign: А не подскажете в каком виде хранить все сессии юзера, я плохо себе это представляю. Сделать таблицу для сессии, в нем поля для ID сессии, поле ID юзера, каждая новая сессия это новая запись в таблице, при выходе пользователя мы удаляем и все записи для данного юзера, я правильно понимаю?
Radist_101: Да, правильно. Можно еще сделать поле ID юзера - уникальным, исходя из вашей задачи наверное - это было бы логично. Тогда не нужен будет before_request и всякие там проверки.
Теперь, когда сессии хранятся на сервере, вы можете сами давать им свои значения.
Например, session_id = md5(user_id + login + соль ).
Ну и писать session_id в базу и в куку юзера.
Radist_101: ага, можно не в md5, а в sha1 засовывать из соображений паранойи.
Но, каждый session_id железно будет уникальным, если кодировать в нем user_id + соль.
В настройках flask-login нашел такой параметр session_protection, это атрибут экземпляра LoginManager.
login_manager = LoginManager()
login_manager.session_protection = 'strong'
При session_protection == 'strong' сеанс будет завершаться принудительно если клиент будет пытаться авторизоваться с разных браузеров и разных IP. Но я пробую авторизоваться с компьютера и с телефона, авторизация проходит без проблем