Пользователи Discourse выходят из системы — как исправить?

Привет! Я получаю сообщения о том, что несколько участников моего форума автоматически разлогиниваются через 20–30 минут.

Я использую SSO, поэтому wondering, не может ли проблема быть связана с тем, что они входят на основной сайт, затем переходят в Discourse (где начинается новая сессия?), после чего возвращаются на основной сайт (в результате Discourse становится неактивным), а затем снова заходят в Discourse и каким-то образом оказываются разлогиненными.

(Хотя это звучит не совсем логично, ведь каждый раз при входе в Discourse тайм-аут бездействия должен сбрасываться до 0, верно?)

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

Вопрос: есть ли настройка, которая предотвращает разлогинивание участников, пока они не были бездействовали в течение X времени? Я не могу её найти.

В настройках Discourse я вижу, что параметр «максимальный возраст сессии» установлен на 1 час, но, думаю, это не должно иметь значения при использовании SSO, верно? (Обратите внимание: когда участник выходит на моём основном сайте, я отправляю сообщение /logout в Discourse, чтобы всё оставалось в порядке. И всякий раз, когда участник выполняет любое действие в Discourse, я обновляю время последней активности на основном сайте, так что проблема не в тайм-ауте основного сайта. Сейчас я добавляю дополнительный отладочный код, чтобы убедиться, что всё работает как надо.)

Спасибо,
E

Это действительно применяется к SSO, так что, скорее всего, это и есть причина вашей проблемы. После часа бездействия сессия Discourse будет завершена, и пользователям потребуется повторная аутентификация через SSO.

Это нормально и вполне допустимо — после 1 часа бездействия они должны выходить из системы.

Проблема в том, что я получаю сообщения о том, что люди выходят из системы уже через 20–30 минут.

Есть ли настройка для этого тайм-аута бездействия в 1 час? Как я уже упоминал в своём первоначальном сообщении, я не могу её найти… и это, кажется, первое место, которое стоит проверить, верно?

Чтобы исключить наиболее очевидную причину… возможно, люди ошибаются относительно точного времени? 30 минут и 1 час не так уж сильно отличаются :wink:

Для продолжения отладки предлагаю следующим шагом изучить данные в таблицах user_auth_tokens и user_auth_token_logs. В них содержится вся информация о токенах сессий и сроках их действия.

Да, это та настройка, о которой вы упоминали в первом посте.

Согласен :wink: Я прямо сейчас это тестирую — захожу на свой сайт, перехожу на форумы, а потом оставляю браузер без присмотра!

Спасибо за советы по таблицам базы данных, я изучу это подробнее.

Хм. Когда пользователи посещают форумы и читают темы и т.д., если они выполняют какое-либо действие (create_post, create_topic, edit_post и т.п.), я получаю сообщение через вебхук. Это информирует основной сайт о том, что пользователь активен, поэтому я могу обновить значение «Последний клик» в его сессии, предотвращая выход из системы. Всё должно работать как надо. Всё отлично.

Однако, если участник просто читает сообщения в течение какого-то времени… время бездействия в Discourse сбрасывается каждый раз, когда он что-то делает (что хорошо), но мой основной сайт никогда не получает сообщений от вебхуков, указывающих на активность пользователя. Поэтому после часа бездействия (кажется, что он зашёл на форумы и отошёл от компьютера) основной сайт считает, что сессия истекла, и выводит его из системы.

Кажется, здесь есть пробел в логике. Для правильной реализации SSO не должен ли быть способ для Discourse сообщать мне, активна ли сессия пользователя (даже если он просто читает)? Возможно, Discourse должен отправлять пинг каждые 5 минут, если участник активен, но не генерирует никаких других сообщений вебхуков.

Или, может быть, когда мой сайт считает, что сессия пользователя истекла, мне следует обратиться к Discourse и спросить, активен ли он там. Есть ли способ сделать это? (Я видел Is there an endpoint to check if a user is logged in - #3 by pfaffman, но не совсем понимаю, подходит ли это для моих нужд, а /session/current.json отсутствует в документации API.) Однако это приведёт к огромному количеству вызовов API — на моём сайте каждую минуту из-за неактивности выводится ~15–20 пользователей, и для каждого из них потребуется вызов (и, возможно, более одного вызова, если у меня нет локального кэша их ID в Discourse).

Друзья, что вы думаете или советуете?

У каждого конечного пункта профиля есть значение last_seen, которое вы можете использовать.

Я не думаю, что видел подобную настройку в каких-либо протоколах SSO, и у нас не было запросов на подобные вещи. Чаще люди держат две системы независимыми.

Если вы действительно хотите создать вебхук для события «пользователь был замечен», вы, возможно, сможете сделать это с помощью собственного плагина.

Не совсем понимаю, что вы имеете в виду под «оставлением двух систем независимыми»? Дайте знать, если я упускаю очевидный способ решения описанной мной проблемы!

В противном случае, мои варианты выглядят так:

  1. Когда пользователь истекает время сессии на основном сайте, перед его выходом из системы, вызвать Discourse и проверить значение last_seen, чтобы узнать, был ли пользователь действительно активен на форуме (просто не делал ничего, что генерирует вызов вебхука). Плюсы: легко реализовать. Минусы: создаст много вызовов API, с чем я уже борюсь и приходится обходить ограничения по частоте запросов.

  2. Создать свой собственный плагин, который будет время от времени опрашивать мой основной сайт, чтобы я мог обновлять время последней активности пользователя на основном сайте. Плюсы: кажется более «правильным» решением (указание активности через push-сообщение); достаточно элегантно. Минусы: сложно реализовать.

  3. Увеличить время выхода из системы на основном сайте до 2 часов. Плюсы: легко реализовать. Минусы: есть ли какие-либо?

  4. Не беспокоиться об этом. Пользователи будут выбрасываться из системы посреди сессии в Discourse и сильно жаловаться. Так у меня сейчас. :wink: Плюсы: легко реализовать, lol. Минусы: очень плохой пользовательский опыт.

Упустил ли я что-то?

Кажется, вариант #3 был бы хорошим решением, хотя мне нужно обдумать последствия увеличения времени сессии на основном сайте.

Мне всё ещё нравится вариант #1 как лучший выбор, но тогда мне нужно разобраться, как предотвратить столько проблем с лимитами частоты запросов. Я бы хотел, чтобы существовал способ глобально отключить все лимиты частоты запросов в Discourse (и в nginx, поскольку я использую установку Discourse через Docker), раз и навсегда. Они мне не нужны. Мой основной сайт общается только с моим экземпляром Discourse. Я не позволяю использовать пользовательские ключи API, и у меня есть только один системный ключ API. Это полностью закрытая система, и лимиты частоты запросов только (постоянно) мешают мне. Думаю, это уже другая тема.

Если вам нужно сохранить описанное вами поведение, то да, я думаю, что это 4 варианта. Но если немного изменить поведение, то оно будет лучше работать с доступными инструментами.

Нестандартным моментом в вашей настройке является:

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

Вы всё ещё можете вызывать /logout, когда пользователь явно выходит из системы на вашем основном сайте. Просто не вызывайте его, когда сессия истекает естественным образом.

По первоначальному сообщению неясно, но вы запускаете специализированный сайт, где люди делятся сверхчувствительной информацией, или где большинство пользователей заходят с общих публичных компьютеров или чего-то подобного?

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

Понял — это хорошее решение; думаю, что достаточно много моих участников используют галочку «запомнить меня» на странице входа, поэтому возвращение их на основной сайт будет незаметным. Если их сеанс на основном сайте истёк, они будут (незаметно) снова авторизованы именно в этот момент. Хм.

Это сайт для сегмента населения, который очень чувствителен к вопросам конфиденциальности. Но я понимаю, что вы имеете в виду, и думаю, что могу просто последовать вашему (и Дэвида) совету.

Огромное вам обоим спасибо. У меня не было чёткого представления о «общей картине» здесь или о том, как другие сайты справляются с подобными сценариями… теперь у меня оно есть :slight_smile: и я вижу несколько возможных решений для моей ситуации. Очень признателен!