Автоматический выход из системы после окончания сеанса

Наше приложение выходит из системы через 30 минут и перенаправляется на страницу входа, я указываю время ожидания сеанса в web.xml и использую requestProcessor для перенаправления. Я хочу показать пользователю сообщение о том, что ваш сеанс истек после истечения сеанса, как я могу сделать это. Автоматический выход из системы? Я хотел бы получить сообщение об ошибке на странице "Время сеанса истекло, пожалуйста, войдите снова" . Тогда как я могу определить время сеанса? какие-либо методы будут срабатывать автоматически?

4 ответа

Решение

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

Вот начальный пример с небольшой помощью jQuery для привязки событий нажатия и нажатия клавиш и запуска ajax-запроса.

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
    $(document).ready(function() {
        $.active = false;
        $('body').bind('click keypress', function() { $.active = true; });
        checkActivity(1800000, 60000, 0); // timeout = 30 minutes, interval = 1 minute.
    });

    function checkActivity(timeout, interval, elapsed) {
        if ($.active) {
            elapsed = 0;
            $.active = false;
            $.get('heartbeat');
        }
        if (elapsed < timeout) {
            elapsed += interval;
            setTimeout(function() {
                checkActivity(timeout, interval, elapsed);
            }, interval);
        } else {
            window.location = 'http://example.com/expired'; // Redirect to "session expired" page.
        }
    }
</script>

Создать Servlet который слушает /heartbeat и делает в основном только следующее:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    request.getSession();
}

чтобы поддержать сессию.

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

Создать реализующий класс Listener HttpSessionListener и определите это в web.xml

Это сообщит вам, когда любая сессия будет уничтожена. Использовать sessionDestroyed() метод.

Смотрите полный пример здесь:

http://www.mkyong.com/servlet/a-simple-httpsessionlistener-example-active-sessions-counter/

Либо это может быть простой сервлет, либо Spring-mvc, либо автоматический выход из системы Spring-security невозможен без совершенной логики на стороне клиента.
Учитывая, что приложение будет иметь оба типа запросов

  • AJAX и
  • отправка формы / перезагрузка страницы

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

Преимущества.


1. Для этого не используются дополнительные вызовы / запросы. с учетом влияния на производительность более 10 тыс. активных пользователей и дополнительных вызовов для автоматического выхода из системы.
2. Однострочная конфигурация с использованием тега.
3. Работает безупречно, даже если пользователь открывает несколько вкладок или несколько окон.
4. Он сообщает вам до 30 секунд аннулирования сеанса, поэтому, если вы заполнили форму, но не отправили ее, вы можете сохранить сеанс (продлить сеанс одним щелчком мыши). Таким образом, пользователь с меньшей вероятностью потеряет несохраненные данные.

Применение


1. Включите сценарий автоматического выхода из системы в требуемые страницы JSP, как указано ниже.

    ....
    </body>
    <jsp:include page="../template/autologout-script.jsp"></jsp:include>
</html>

2. Создайте страницу JSP, autologout-script.jsp и добавьте код ниже. Примечание: редактирование / настройка не требуется

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<script>
$(document).ready(function()
{
    var timeOutTimeInSeconds = ${ timeOutTimeInSeconds }; 
    var showTimerTimeInSeconds= ${ showTimerTimeInSeconds };

    var sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);
    var timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);
    var badgeTimerId;
    window.localStorage.setItem("AjaxRequestFired", new Date());

    function redirectToLoginPage(){
        //location.href =  '<c:url value="/" />'+'${loginPageUrl}';
        window.location.reload();
    }

    $(document).ajaxComplete(function () {
        resetTimer();
    });

    $(window).bind('storage', function (e) {
         if(e.originalEvent.key == "AjaxRequestFired"){
             console.log("Request sent from another tab, hence resetting timer")
             resetTimer();
         }
    });

    function resetTimer()
    {
        showTimerTimeInSeconds= ${ showTimerTimeInSeconds };

        console.log("timeOutTimeInSeconds : "+timeOutTimeInSeconds)
        window.localStorage.setItem("AjaxRequestFired", new Date());

        window.clearInterval(sessionCheckIntervalId);
        sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);

        window.clearInterval(timerDisplayIntervalId);
        timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);

        hideTimer();
    }

    function showTimer()
    {
        $('#sessionTimeRemaining').show();
        $('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
        window.clearInterval(timerDisplayIntervalId);
        badgeTimerId = setInterval(function(){
            $('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
        }, 1000);
    }

    function hideTimer()
    {
        window.clearInterval(badgeTimerId);
        $('#sessionTimeRemaining').hide();
    }
});
</script>

3. Настройте атрибуты сеанса для настройки параметра тайм-аута. Примечание. Настройте его после создания сеанса. Вы можете реализовать метод HttpSessionListener sessionCreated и установить следующую конфигурацию в соответствии с вашими требованиями.

session.setMaxInactiveInterval(300);

session.setAttribute("timeOutTimeInSeconds", 300);
session.setAttribute("showTimerTimeInSeconds", 30);

4. Добавьте ниже html для отображения таймера.
Примечание: его можно переместить на страницу шаблона сценария автоматического выхода, если вы хорошо разбираетесь в CSS. Следовательно, вы можете избежать добавления этого на каждой странице.
Включите bootstrap или добавьте свой собственный CSS.

<span class="badge badge-primary" title="click to keep session alive" id="sessionTimeRemaining" 
    onclick="ajaxSessionRefresh()" style="display:none;">
    <i class="badge badge-danger" id="sessionTimeRemainingBadge" style="float:left">30</i>
     &nbsp; 
     <small>Refresh</small>
     <i class="glyphicon glyphicon-refresh"></i>
</span>

Это все о простой реализации автоматического выхода из системы. Вы можете скачать рабочий пример из моего репозитория github.
Autologout с использованием простого примера сервлета.
Autologout с использованием примера конфигурации java
spring -security.

Объяснение логики


Случай 1: при загрузке страницы
Здесь логика проста, при загрузке страницы установите таймер интервальных формул на maxInactiveInterval. после тайм-аута перенаправление на страницу входа.
Случай 2. Следите за вызовами AJAX.
Теперь, учитывая запросы AJAX, вы можете использовать обратные вызовы.ajaxStart() или.ajaxComplete() jquery, чтобы при запуске любого запроса ajax вы могли сбросить интервал.
Случай 3: Отслеживание активности нескольких вкладок / окон
Обмен данными между таблицами выполняется для синхронизации состояния каждой вкладки. Используется localStorage при изменении события.

Необходимые ограничения / улучшения
1. Если максимально разрешенный сеанс равен одному, если сеанс взят из другой системы, запрос AJAX завершится ошибкой. Это необходимо для перенаправления на страницу входа.
2. Используйте ajaxStart() вместо ajaxComplete() для точной синхронизации значений idleTime между сервером и браузером.

Требования
1. JQuery

Сравнение альтернатив текущей реализации


1. Установка заголовка Обновить в HTTP-ответе. (Не работает для запросов AJAX)

response.setHeader("Refresh", "60; URL=login.jsp");
  1. Установка мета-тега обновления в HTML (не работает для запросов AJAX)
<meta http-equiv="refresh" content="60; url=login.jsp">
  1. Настройка средства проверки активности Поддерживает сеанс в рабочем состоянии с помощью повторного запроса AJAX. Отслеживает время простоя и делает запрос на выход по истечении тайм-аута.
    Несомненно, это хороший вариант с простой логикой. Но я хочу просто записать свои наблюдения.
    • Влияние на производительность, если в минуту выполняется 2 запроса для поддержания активности сеанса и 50 тыс. Активных пользователей. 100к запросов в минуту.
    • Связь между вкладками Если открыты две вкладки, одна вкладка получает активность, а другая вкладка не получает активности, эта вкладка запускает запрос выхода и аннулирует сеанс, даже если активность присутствует на другой вкладке. (Но с этим можно справиться)
    • Принудительный выход из системы. Клиент доминирует над сервером, чтобы аннулировать сеанс.

Включите в JSP вспомогательную функцию javascript и пингуйте сервер каждые 31 минуту. Вышеупомянутая служебная функция должна использовать внутреннюю функцию setTimeout().

setTimeout ( "checkServerSession()",  /* intervalInMilliSeconds */ 31000);

Обратите внимание, что

checkServerSession()

обычная функция JS, которая может запускать HTTP-запросы Если запрос успешен, сеанс существует, в противном случае покажите подсказку пользователю.

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

Другие вопросы по тегам