Это странно. У нас есть веб-сайт Laravel, и на указанном сайте у нас есть таймер на пользователя, где они получают 15 минут неактивности перед загрузкой.
Мы делаем это через таймер, который находится на странице в реагирующем компоненте, он работает так, как мы хотим, но теперь у нас есть новая проблема: если пользователь вошел в систему и закрыл крышку своего ноутбука, веб-сайт должен загрузить их , Это делают банки, школы и университеты, правительственные сайты тоже. Так что возможно, просто не уверен как.
Мы используем веб-сокеты, используя библиотеку laravel-websockets и Echo. Я хотел бы, чтобы это произошло:
- Как только вы закроете свой ноутбук, загрузитесь к экрану входа. Поэтому в следующий раз, когда вы откроете ноутбук и войдете в систему, вы увидите браузер на экране входа в систему. Это не должно происходить так быстро, но нам нужен способ отправить что-то внешнему интерфейсу, в основном, сказать им, чтобы они обновляли страницу, когда сеанс завершается, мы устанавливаем время жизни сеанса на уровне 15 минут.
Некоторые люди предложили в других подобных вопросах:
- создать собственный обработчик веб-сокета
- Чтобы сравнить cookie-файл сеанса (в браузере) с cookie-файлом пользователя на серверной части.
- Чтобы таймер работал на передней панели (у нас он останавливается, когда вы закрываете крышку ноутбука)
Наиболее популярным кажется использование веб-сокетов, прислушиваясь к тому, что пользователь отключается, а затем загружает их, и это нормально, но как же тогда вы отправляете запрос в браузер, который приостановлен, чтобы затем загрузить их?
Я нашел requestIdleCallback () Но, опять же, я не думаю, что это то, что я хочу, если у меня уже есть таймер сердцебиения на сайте. Это также не работает во всех браузерах.
Я очень запутался здесь, как это сделать, пример, который я могу привести:
Войдите в свой банк, переведите компьютер в спящий режим, подождите 15-20 минут, разбудите компьютер, войдите в систему и увидите, что ваш банк теперь отображает вас на экране входа в систему. Вот чего я хочу . Но я не знаю, как этого добиться.
Вы не можете отправлять события в «спящий» браузер с бэкэнда, и хотя да, это должно быть бэкэнд-решение, как вы тогда обновите интерфейс, чтобы они были на экране выхода из системы, когда они пробуждают ноутбук? или компьютер?
источник
Ответы:
ОБНОВИТЬ
Что касается запроса WebSocket, я предполагаю, что вы используете Laravel WebSockets с
pusher
. Pusher.io не поддерживает тайм-аут , вы можете прочитать эту статью поддержки "Планируете ли вы добавить функцию тайм-аута соединения в клиентскую библиотеку Channels pusher-js?" , Вы можете проверить это, если включите режим отладки Laravel (APP_DEBUG=true
внутри.env
) и начнетеlaravel-websockets
с терминала (php artisan websockets:serve
), чтобы вы могли видеть события выходного журнала. Если вы пытаетесь закрыть ноутбук крышку или набор компьютер в режим гибернации ( спящий ), вы не увидите никаких сообщений относительно этого события. Вы не можете сделать это сpusher
протоколом. Есть событие Присутствияmember_removed
, но срабатывает только при закрытии вкладки или выходе из системы. Конечно , вы можете запустить ваш клиент пользовательского события в канал присутствия, но для этого необходимо также установка таймера на сторону клиента , и вы должны будете создать поставщик услуг дляlaravel-websockets
сервера , как этот GitHub вопрос «существует путь к реализовать вебхуки? ,Это происходит потому, что таймеры клиента останавливают выполнение в спящем режиме, поэтому они продолжают с того места, где были раньше. Но если вы используете переменную даты для экономии времени , эта переменная не будет обновляться, когда компьютер перейдет в спящий режим, поэтому вы узнаете, когда он выйдет из спящего режима, проверив эту переменную даты, которая по сравнению с текущим временем будет иметь значительное значение. Разница и будет больше, чем интервал таймера.
Реализация временной логики в клиенте
Вы также можете увидеть эту реализацию для этой связанной Q / A : могут ли какие-либо браузеры настольных компьютеров определять, когда компьютер выходит из спящего режима?
Вы можете настроить таймер в клиенте для запуска каждую минуту. Мы не будем полагаться на интервал таймера , но вместо этого этот таймер проверит внешнюю переменную области видимости, если промежуток времени с последнего таймера больше
15
минут; если это так, то это означает, что браузер / JS по какой-то причине остановил выполнение , возможно, спящий режим устройства ( спящий режим ), а затем вы перенаправили пользователя на маршрут выхода из системы.Пример кода клиента JS:
Вы можете проверить этот простой пример, но используя. Лучше всего протестировать его на ноутбуке с закрытой крышкой, а затем снова открывать через1
второй таймер с15
выходом из системы здесь15 секундкаждую минуту, потому что если у вас много запущенных программ, компьютеру требуется некоторое время, чтобы сохранить состояние памяти, чтобы завершить режим гибернации и остановить выполнение.Пример веб-работников
Вы даже можете использовать API Web Workers, чтобы настроить веб-работника как можно более безопасно:
Код JS страницы:
logoutWorker.js
Код веб-работника :Вы также можете проверить пример Web Worker с тем же
15
таймером секунд здесь .источник
clientSession
переменную. Вы можете проверить мой ответ снова, я даже добавил пример Web Worker.?v=1
в конце.Во-первых, давайте рассмотрим, почему веб-сайты Banking выходят из системы через 15 минут без активности. Это требование PCI для безопасности.
Требование PCI-DSS 8.1.8 :
Чтобы достичь этого, решение на самом деле гораздо более примитивно, чем вы думаете . Он не требует использования веб-сокетов и не знает ничего о состоянии компьютера клиента (в спящем режиме, в режиме бодрствования или иным образом). Все, что требуется, это знать время между текущим запросом, использующим этот сеанс, и последним запросом, использующим тот же сеанс, и убедиться, что они не превышают 15 минут. Если они - пользователь, должен быть повторно аутентифицирован. Если это не так, вы можете продолжить запрос.
Сообщение об истечении времени сеанса
Вы, вероятно, затем задаетесь вопросом (если это так просто), как появляется сообщение о превышении времени ожидания сеанса, когда вы переводите компьютер в спящий режим и включаете его снова. Эта часть обманчиво проста.
Когда компьютер переводится в спящий режим, браузер фактически отключает все соединения TCP / IP, что, в свою очередь, отключает цикл обработки событий в движке javascript. Так что таймеры не работают. Но когда браузер снова просыпается, он пытается обновить некоторые вещи, включая саму страницу. Таким образом, когда страница обновляется, запрос возвращается на сервер, вызывая сервер, чтобы потребовать повторной аутентификации пользователя.
Однако это не будет учитывать модальное сообщение javascript (если это то, на что вы ссылаетесь), которое делают некоторые банковские сайты. Также не все браузеры делают жесткое обновление на странице во всех сценариях. Таким образом, можно использовать другой подход. Вместо того, чтобы иметь таймер в браузере, который истекает через 15 минут, вы можете просто сохранить время загрузки страницы в javascript как метку времени и иметь интервал времени в 1 секунду, который сравнивает эту метку времени с текущей меткой времени компьютера. Если они находятся на расстоянии более 15 минут, сеанс должен быть прекращен.
Даже если компьютер переходит в спящий режим и таймер останавливается, сессия будет в конечном итоге истекать на стороне сервера ( подробности см. В разделе ниже ), а когда компьютер снова просыпается, таймер с интервалом в 1 секунду в конечном итоге снова запускается, вызывая сообщение (как будто время ожидания пользователя истекло, пока компьютер спал). Время, потерянное между временем, в течение которого компьютер перешел в спящий режим, и временем, в течение которого компьютер просыпается, не будет иметь значения, поскольку отметка времени останется в памяти. Разрыв между клиентом и сервером не важен, потому что им не нужно передавать эту информацию для правильного завершения сеанса на стороне сервера. Сервер может выполнить свою собственную сборку мусора и завершить сеанс без связи с клиентом (т.е. асинхронно ).
Верьте или нет Банки не заботятся о деятельности внутри клиента. Они заботятся только об активности запросов к серверу. Поэтому, если вам интересно, как они поддерживают сеанс в течение более 15 минут, когда пользователь находится на одной и той же странице в течение такого длительного времени, они просто отправляют AJAX-запрос в фоновом режиме, чтобы обновить сеанс после запроса пользователя, если они все еще хочу продолжить.
Это можно сделать в том же
onload
обратном вызове события, который мы использовали ранее, так:Обработка завершения сеанса на стороне сервера
Для обработки завершения сеанса на стороне сервера существует несколько подходов. В зависимости от того, какой из них вы используете, вам понадобятся разные тактики. Один использует обработчик сеанса PHP по умолчанию и устанавливает
session.max_lifetime
срок действия истекает через 15 минут (это полностью удаляет данные сеанса на стороне сервера, что делает недействительным куки-файл клиента).Если вы позволите механизму обработчика сеанса по умолчанию сделать это, вы можете столкнуться с проблемами в зависимости от того, какой обработчик используется (файлы, memcached, redis, custom и т. Д.).
С файлами (обработчик по умолчанию) сборка мусора происходит одним из двух способов:
session.max_lifetime
. Проблема с этим подходом состоит в том, что на узлах с низким трафиком сеанс потенциально может находиться там на сервере в течение длительного времени, пока не поступит достаточное количество запросов (в зависимости отsession.gc_probability
оценки), чтобы вызвать GC для очистки файлов сеанса.С обработчиками на основе memcached и redis у вас нет этой проблемы. Они будут обрабатывать очистку памяти автоматически. Сессии могут все еще оставаться в физической памяти некоторое время после их жизни, но демон не сможет получить к ним доступ. Если вы беспокоитесь об этом бите для безопасности, вы можете зашифровать свои сеансы в покое или найти хранилище ключей / значений, которое имеет более строгий механизм очистки памяти GC.
С пользовательским обработчиком сеанса вам придется создать свой собственный механизм GC. Через него
SessionHandlerInterface
вы реализуетеgc
метод, который передает вам максимальный интервал времени жизни сеанса, и вы будете нести ответственность за проверку того, прошел ли сеанс свое время жизни на основе этого интервала, и выполнить оттуда сборку мусора.Вы также можете установить отдельную конечную точку, которая проверяет TTL сеанса (через асинхронный AJAX-запрос на стороне клиента) и отправляет ответ, если сеанс истек (что заставляет javascript повторно аутентифицировать пользователя).
источник
Так что Idea стоит за setInterval и Sockets, setInterval поддерживается в большинстве браузеров, а javascript WbsocketApi поддерживается почти в каждом браузере.
Краткий обзор: setInterval () - это поведение функции, когда ваш компьютер находится в спящем / приостановленном / спящем режиме, он находится в режиме паузы, а когда вы находитесь в режиме пробуждения, он возобновляет работу.
Следующий код выполняет следующее: сначала (может быть, но одновременно) запускает php server_socket для прослушивания соединений,
чем javascript websocket API отправляет текущую метку времени в миллисекундах метки времени Unix каждые 2 секунды, вы можете иметь 1 секунду, это зависит от вас.
после того, как сокет этого php-сервера получает это время и проверяет, есть ли у него что-то похожее на предыдущий раз для сравнения, при первом экземпляре кода php не имеет ничего похожего на предыдущий раз, чтобы сравнить его со временем, которое было отправлено из javascript websocket, поэтому php ничего не делает, но сохраняет это время в сеансе с именем «prev_time» и ожидает получения данных другого времени из сокета javascript, поэтому здесь начинается второй цикл. когда сокет php-сервера получает новые данные о времени из javascript WebsocketApi, он проверяет, имеет ли он что-то похожее на предыдущий раз, чтобы сравнить с этими вновь полученными данными о времени, это означает, что php проверяет, существует ли сессия с именем «prev_time», так как мы во втором цикле php обнаруживает, что он существует, захватывает его значение и делает следующее
$diff = $new_time - $prev_time
, $ diff будет 2 секунды или 2000 миллисекунд, потому что помните, что наш цикл setInterval происходит каждые 2 секунды, а формат времени, который мы отправляем, в миллисекундах,чем PHP проверяет,
if($diff<3000)
если разница меньше 3000, если он знает, что пользователь активен, снова вы можете манипулировать этими секундами, как вы хотите, я выбираю 3000, потому что возможная задержка в сети, что почти невозможно, но вы знаете, что я всегда осторожен, когда это касается сетей, поэтому давайте продолжим, когда php определит, что пользователь активен. php просто сбрасывает сеанс 'prev_time' со значением,$new_time
которое было недавно получено, и просто для целей тестирования отправляет сообщение обратно в сокет javascript,но если
$diff
это больше 3000, это означает, что что-то приостановило наш setInterval, и есть только один способ, которым это может произойти, и я думаю, что вы уже знаете, что я говорю, поэтому вelse
логике (if($diff<3000)
) вы можете выйти из системы, удалив конкретную сессию, и если вы Если вы хотите перенаправить, вы можете отправить текст в сокет javacript и создать логику, которая будет выполняться вwindow.location = "/login"
зависимости от текста, вот код:Сначала это файл index.html просто для загрузки javascript:
тогда это javascript, он не очень красиво закодирован, но вы можете понять, ЧИТАЙТЕ КОММЕНТАРИИ, ОНИ ВАЖНЫ:
Теперь это часть php-кода, не волнуйтесь, там тоже есть полный код, но эта часть на самом деле делает то, что делает вышеупомянутые задания, вы встретите и другие функции, но они предназначены для декодирования и работы с сокетами javascript, так что это действительно правильно здесь ПРОЧИТАЙТЕ КОММЕНТАРИИ, ОНИ ВАЖНЫ:
А вот полный код php:
ЗАМЕЧАНИЕ ЧИТАЙТЕ ЭТО:
$new_time
переменная находится$jsTime
в кодесоздайте папку и просто скопируйте и вставьте ее в файлы, запустите php socket с помощью команды: php -f server_socket.php перейдите на локальный хост и протестируйте его, откройте консоль, чтобы увидеть сообщения, в которых будет указано «вы активны» или «вы не активны» (когда ты выходишь из сна); ваше выполнение будет происходить, когда пользователь выйдет из спящего режима, а не когда он спит, потому что в этот момент все кэшируется в файл подкачки (windows) или в swap (linux)
источник
Я думаю, у меня есть идея, вы много обсуждали о том, как работает система входа / выхода из банка.
Случай 1: Доступ пользователя к веб-странице в течение неограниченного времени, если пользователь активен
Всякий раз, когда пользователь вошел в систему, запустите таймер на своем бэкэнде (установите ограничение по времени, сколько хотите), скажем, 15 минут. Теперь, что это значит? Это означает, что если пользователь не выполняет никаких действий на веб-странице, мы вышлим его / ее из системы.
Теперь спереди вы можете отправить пользовательскую активность на ваш бэкэнд (может быть отправлен с использованием сокета или длинного опроса), что в основном сбрасывает таймер, и пользователь может активно использовать веб-страницу в любое время по своему усмотрению.
Если пользователь переводит свой компьютер в спящий режим, таймер не будет сброшен, и вы можете отменить сеанс, как только таймер закончится.
Если вы хотите сделать недействительным пользовательский сеанс, как только он переведет компьютер в спящий режим, вы можете установить ограничение времени проверки сеанса. Например, когда пользователь входит в систему, мы создадим сеанс, который будет действителен только в течение 10 секунд, и как только мы получим запрос активности пользователя, мы можем сбросить таймер и предоставить новый ключ сеанса.
Я надеюсь, это поможет вам. Дайте мне знать, если у вас есть какие-либо вопросы.
источник
Я написал сценарий, чтобы определить, ушел ли аппарат в спящий режим. Идея в том, что когда машина находится в спящем настроении, все сценарии будут остановлены. Поэтому, если мы будем отслеживать текущее время в течение timeInterval. Каждый раз, когда timeInterval запускает текущее время минус (-), новое время должно быть достаточно близко к timeInterval. Поэтому, если мы хотим проверить, не работал ли таймер в течение X времени, мы можем проверить, больше ли разница во времени, чем X.
Пример удара проверяет, был ли компьютер переведен в спящий режим более чем на 15 секунд. Обратите внимание, что, когда вы переводите компьютер в спящий режим, потребуется еще 15 секунд, чтобы представить все процессоры. (При тестировании на МОЕМ ПК).
источник
Я выполнил точно такое же требование, используя AWS Cognito, с Lambda Authorizers & Redis, я не могу поделиться кодом на этом этапе, но я могу рассказать вам все, как он реализован с этими компонентами, те же концепции можно использовать с другими не AWS компоненты.
Во-первых, при реализации выхода из неактивности вам придется делать это на стороне сервера, как если бы кто-то просто выключил свой компьютер, интерфейсный веб-сайт не мог бы выйти из него. Я использовал концепцию
ACTIVE
пользователей. Когда пользователи успешно проходят аутентификацию, я сохраняю в Redis с TTL 15 минут запись с ключом ихusername
& значениемACTIVE
(это может быть имя пользователя + sessionid, если вы хотите разрешить несколько сеансов для данного пользователя одновременно).В моих пользовательских Авторизаторах, когда у пользователя есть
ACTIVE
& у него есть действующий токен, я даю ему доступ к защищенному ресурсу И, что наиболее важно, я делаю еще один вклад в Redis сusername
&ACTIVE
.Всякий раз, когда пользователь выходит из системы, я выхожу из него в своем решении для управления идентификацией (Cognito) и помечаю их как
INACTIVE
. Обратите внимание, что если пользователь не нажмет на API в течение 15 минут, у него больше не будет записиACTIVE
против своего имени пользователя, и он больше не сможет получить доступ к API и должен будет снова войти в систему, для чего он будет перенаправлен.При таком подходе нужно учитывать много вещей, во-первых, часто Авторизаторы кешируют результаты в течение некоторого времени, и если, к примеру, вы кешируете результат в течение 5 минут в качестве примера, то ваш пользователь может выйти из системы через 10 минут как ваш пользователь. может ударить кеш вместо Авторизатора, который не обновит
ACTIVE
запись.Также важно убедиться, что все, что вы используете для хранения, если данный пользователь
ACTIVE
является высокодоступным и быстро восстановится в случае сбоя.Подход использования хранилища кэша таким способом аналогичен тому, как аннулирование токена модифицируется для протоколов авторизации без сохранения состояния, таких как OAuth2.
Мы использовали этот подход уже несколько месяцев, и, похоже, он нам подходит, это может быть немного раздражающим требованием, я ожидал, что в мире AWS будет готов к использованию. коробочного решения для этого, но не о чем было говорить.
источник