Обработка времени ожидания сеанса пользователя в приложениях SaaS - обсуждение нескольких подходов

11

Я знаю, что у этого есть большой шанс быть отмеченным как дубликат, но не мог найти точно, что я ищу

Это общая проблема, и я уверен, что у нее есть четкое решение для лучшей практики

Фон

  1. Одностраничное SaaS-приложение с множеством перетаскиваний, пользователь может взаимодействовать с ним без особой связи с сервером в течение некоторого времени.

  2. Сеанс сервера содержит только пользовательский объект с использованием непостоянного файла cookie сеанса.

  3. Сессия истекает на сервере через X часов

  4. Некоторые вещи загружаются только при входе

проблема

  1. Пользователь работает над приложением, после чего пользователь не выходит из системы, просто держит браузер открытым
  2. Пользователь возвращается через более чем X часов (сессия недействительна на сервере)
  3. Пользователь взаимодействует с приложением без необходимости подключения к серверу (перетаскивает объекты, редактирует текст ...)
  4. Только при следующем взаимодействии с сервером (предположим, что автосохранение отсутствует) пользователь попадает на страницу входа и теряет часть своей работы.

Возможные решения

Вот некоторые решения, которые я имею в виду, хотел бы услышать, есть ли какие-то другие, и есть ли какие-либо принципиальные проблемы с любым из них.

1. Никогда не выходите из системы

  • Как? либо сохраняйте длинный сеанс, сохраняйте постоянный файл cookie, либо пинг "keep alive" с помощью javaScript
  • Плюсы : пользователю не нужно ни о чем беспокоиться, он решает за него проблему
  • Недостатки : не соответствует PCI, небезопасен и требует изменений в разработке, например, вещи, загруженные в сеанс только при входе пользователя в систему, должны быть перемещены либо в подмодель паба (прослушивание изменений события), либо в тайм-ауте кэша.

2. Локальное хранилище

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

3. Автосохранение

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

  • Как? Используйте инфраструктуру MV ** (Backbone.js / Knockout.js / Ember.js / Angular.js и т. Д.), Чтобы связать модель и сохранить изменения.
  • Плюсы : похоже на чистое решение, сеанс активен, пока пользователь активен, работа на стороне клиента не выполняется без его сохранения.
  • Минусы : последнее действие, которое пользователь выполняет после истечения времени ожидания сеанса.

4. Выйдите из системы после окончания сеанса

это может иметь несколько подходов

  1. Задать вопрос серверу «истек ли сеанс» - это что-то вроде уловки 22 / Кот Шредингера, так как простой вопрос к серверу продлевает сеанс (перезапускает тайм-аут),

    • Как? Либо есть сервер, который поддерживает такой вопрос (я не знаю ни одного, но я пришел из земли Java), или можно просто сохранить таблицу идентификаторов сеансов и время последнего доступа вручную, и запросить сервер, передав сеанс Идентификатор в качестве параметра вместо cookie, я не уверен, что это вообще возможно, но это звучит опасно, небезопасно и плохо оформляет страницу whatsoever.login, сохраняется после входа в систему
    • Плюсы : если была такая встроенная поддержка на серверах, звучит как чистый, законный вопрос (спрашивать, есть ли у пользователя X сеанс или нет, не обновляя его, если он это делает)
    • Минусы : если сервер его не поддерживает (и опять же, я не знаю, есть ли у этой функции какой-либо сервер или фреймворк), то обходной путь потенциально может привести к огромным угрозам безопасности.
  2. Один из обходных путей, о котором я слышал, это короткий сеанс на стороне сервера и поддерживающий пинг на стороне клиента, который имеет максимальное количество пингов

    • Как? Короткий сеанс на сервере, клиент пингует каждый sessionTimeOut / 2, имеет максимальное количество попыток Y.
    • Плюсы : вид исправляет проблему, быстро и грязно
    • Минусы : ощущается как хак, обрабатывая обновление сессии самостоятельно, а не позволяя серверу делать это
  3. Таймер на стороне клиента

    • Как? Имейте таймер на стороне клиента и синхронизируйте его с сервером, перезапуская его при каждом запросе, чтобы быть равным максимальному тайм-ауту сеанса сервера минус некоторое заполнение, после того как пользователь не отправляет какой-либо запрос на сервер, пользовательский интерфейс показывает, что «сеансы о времени ожидания, вы хотите продолжить? (как у вас на онлайн-банкинга)

    • Плюсы : исправляет проблему

    • Минусы : не могу думать ни о чем, кроме необходимости убедиться, что синхронизация работает

Вопрос

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

Эран Медан
источник
Я использую angular и django с tastypie, так что вот мои мысли с этой точки зрения: 4.1: Класс аутентификации, используемый для всех ваших ресурсов, может проверять и сравнивать разницу во времени между сейчас и значением поля «последний доступ» в вашем пользователе модель. 401 - это время больше настроенного таймфрейма. 200 в противном случае и обновите поле 'last-access' с помощью now. 4.2 звучит как отличный способ убить ваш сервер и увеличить затраты. 4.3 На Android, когда я возвращаюсь на домашний экран, я почти уверен, что процесс приостановлен, и это также может помешать вашему клиентскому таймеру.
Airtonix

Ответы:

5

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

Локальное хранение и автосохранение создают некоторые проблемы с транзакциями и тем, что на самом деле означает сохранение. Я участвовал в нескольких проектах, где оказалось, что это больше проблем, чем стоит, когда пользовательская база не понимает механики, стоящей за этим.

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

Билл
источник
2

Один из обходных путей, о котором я слышал, - это короткий сеанс на стороне сервера и пинг keep> alive на стороне клиента, который имеет максимальное количество

Как? Короткий сеанс на сервере, клиент пингует каждый sessionTime / 2, имеет максимум> повторов Y. Плюсы: Вид решает проблему, быстрый и грязный Минусы: похоже на хак, обрабатываете обновление сеанса самостоятельно вместо того, чтобы> позволить серверу сделать это

Это на мой взгляд лучшее решение. Почему вы считаете это "грязным взломом"?

Это делает именно то, что должно быть сделано. Пока пользователь работает с программой, сессия останется открытой.

После того, как пользователь перестанет работать с программой, сеанс будет закрыт.

Достаточно просто для реализации.

Именно то, что нужно, если я правильно понял вопрос.

johnfound
источник
Иногда грязные хаки - лучшие решения :) спасибо. Вы правильно поняли вопрос
Эран Медан
2

Я на самом деле создаю приложение, которое занимается этим.

Я начал с создания сервиса RESTful, используя Django, Guradian и Tastypie. Он аутентифицируется только с помощью APIKEY, авторизация для объектов осуществляется Guardian.

Приложение django имеет только один шаблонный вид urlconf, который загружает base.html, который ...

На стороне клиента я создал приложение, используя Angular.

Что касается аутентификации, существует http-auth-interceptor, который прослушивает 401 ответ.

Когда 401 получен, он буферизирует исходящий запрос и запускает событие «Требуется вход в систему». Это может произойти несколько раз.

У меня есть модальное всплывающее окно, содержащее форму входа в систему, которая отображается, когда слышно событие «Требуется вход в систему», и она выполняет вход в систему, который возвращает ресурс пользователя (пакет JSON), который также содержит APIKEY.

Все буферизованные запросы, которые ранее приводили к ответу 401, воспроизводятся с APIKEY, теперь включенным в заголовок http авторизации.

Я использую другой угловой сервис / фабрику для управления локальными данными JSON, и именно там я храню имя пользователя и apikey.

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

Возможно, используйте проверку метки времени из последнего действующего http-запроса.

airtonix
источник
В качестве продолжения этого я рассмотрел возможность следующего сравнения для каждой проверки вкусности пирога: current_time> user.lastlogin_time + settings.SESSION_TIMEOUT. затем верните 401, если истина. Каждая действительная аутентификация обновляет user.lastlogin_time до current_time.
Airtonix
Это довольно мило, и как я тоже думал об этом.
oligofren
1

В моем случае я использую что-то похожее на 4.1. После того, как пользователь войдет в систему с очень легковесным угловым приводом, запрос JSON AJAX поступает в REST API через заданные интервалы к серверу. Из-за требований безопасности собственный интерфейс пользователя ожидает, что сервер будет поддерживать сеанс для пользователя, который хранит некоторую защищенную информацию, шаблоны, данные и т. Д. На стороне сервера. Это все еще мой предпочтительный метод с точки зрения безопасности. Когда имеешь дело с конфиденциальными данными (не только хэшированными паролями и т. Д.), Хранение IMO на стороне клиента в локальном хранилище и т. Д. Представляет больший риск, чем на стороне сервера (я уверен, что кто-то будет обсуждать это со мной). Третьи стороны используют тот же API при взаимодействии с системой, но должны отправлять учетные данные для аутентификации при каждом запросе.

Сеанс на сервере имеет максимальное время простоя, примененное к нему, и механизм хранения сеансов записывается в кэш-память (к которому также применяется максимальное время жизни, и в этот момент сеанс памяти будет помечен как истекший). Время жизни должно быть только больше, чем время жизни сессии, которое вы абстрагируете в приложении (и не должно быть моим). Например, сеанс может не истечь, пока он не простаивает в течение 48 часов, если речь идет о сервере, но ваш код контролирует фактическое время жизни. Это может привести к проблемам с ресурсами, если это время жизни слишком велико и вы плохо справляетесь с управлением сессиями.

В моем случае у разных пользователей могут быть разные тайм-ауты простоя в зависимости от их ролей в организации. Сервер устанавливает максимальные ограничения на время жизни сеанса, но пока пользовательские ограничения меньше этих, он работает просто отлично. Как только сервер заканчивает сеанс, это спорная проблема, поскольку процесс истечения сеанса уже был бы обработан приложением изящно. Это требование того типа бизнес-приложения, которое я создал.

Как только сеанс пользователя простаивает и находится в пределах заданного пороговым значением приложения, API будет инструктировать пользовательский интерфейс для отображения диалогового окна обратного отсчета (как это делают банки), и как только оно будет в пределах определенного промежутка времени во времени от истечения, оно изящно выходит из системы Эта функция сохраняется во всех окнах браузера (поскольку сервер находится под контролем), и событие простоя в любом окне запускает изящный таймер и процесс автоматического выхода из системы (и поддерживает их синхронизацию).

Если случайно сеанс заканчивается незаметно (сеансы сбрасываются в memcached), следующий запрос, влияющий на сервер, уведомит пользователя и вернет его обратно на круги своя (редко случается, но может).

Крис
источник