Подтвердить что ты не робот

Как автоматически выйти из системы с помощью Spring Безопасность

У меня есть веб-приложение spring, и я выполнил аутентификацию пользователя с помощью spring безопасности.

Все работает хорошо. Вход и выход прекращаются!

Теперь я хочу реализовать, чтобы автоматически выйти из системы. Например, если у пользователя открылось окно около 30 минут и ничего не предпринимается (сеансы истекли, например), система должна выйти из системы автоматически. Как я могу это реализовать?

Он может быть реализован на стороне клиента (я отправляю запросы каждые 1 минуту и ​​проверяю, завершен ли сеанс). Но не могу ли я сделать это автоматически из Spring?

У меня есть эта конфигурация:

<http auto-config="true" use-expressions="true">


        <intercept-url pattern="/admin**" />
        <access-denied-handler error-page="/403" />

        <form-login login-page="/login" 
            default-target-url="/admin"
            authentication-failure-url="/login?error" 
            username-parameter="NAME"
            password-parameter="PASSWORD"  />

        <logout invalidate-session="true" 
             logout-success-url="/login?logout"/>

    </http>

и в web.xml

<session-config>
  <session-timeout>1</session-timeout>
</session-config>

через 1 минуту я вижу, что сеанс был уничтожен. убить сеанс через 1 минуту. но страница не была перенаправлена ​​на/login? logout

4b9b3361

Ответ 1

Как использовать конфигурацию безопасности. Надеюсь, ниже config: будет работать.

applicationContext.xml

 --namespace-> xmlns:security="http://www.springframework.org/schema/security"

        <security:logout invalidate-session="true"
                        success-handler-ref="Logout"
                        logout-url="/logout.html" />
        </security:http>

web.xml

 <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>

И им, вам нужно написать свой собственный, потому что success-handler-ref = "Выход" - это настраиваемый обработчик для выхода:
Выход @Component

public class Logout extends SimpleUrlLogoutSuccessHandler {

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {

        if (authentication != null) {
            // do something 
        }

        setDefaultTargetUrl("/login");
        super.onLogoutSuccess(request, response, authentication);       
    }
}

Ответ 2

Вы можете использовать глобальное значение таймаута, поместив его в свой web.xml:

<session-config>
  <session-timeout>30</session-timeout>
</session-config>

Ответ 3

Вот учебник, который я использовал. Существует java script и код на стороне сервера. Сервер будет вычислять, когда сессия истечет и отправит ее в виде файла cookie. Тогда java script будет проверяться каждые 10 секунд, если он истек, если это так, будет window.close(). http://www.javaworld.com/article/2073234/tracking-session-expiration-in-browser.html

Вот как я его реализовал

SessionTimeout.js

/**
 * Monitor the session timeout cookie from Apache and log the user out when expired
 */
"use strict";

var jQuery = require("jquery").noConflict();
var jsCookie = require("js-cookie");

module.exports.registerListener = function() {
    calcOffset();
    checkSession();
};

/**
 * We can't assume the server time and client time are the same
 * so lets calcuate the difference
 */
function calcOffset() {
    var serverTime = jsCookie.get('serverTime');
    serverTime = serverTime==null ? null : Math.abs(serverTime);
    var clientTimeOffset = (new Date()).getTime() - serverTime;
    jsCookie.set('clientTimeOffset', clientTimeOffset);
}

/**
 * Check the sessionExpiry cookie and see if we should send the user to /
 */
function checkSession() {
    var sessionExpiry = Math.abs(jsCookie.get('sessionExpiry'));
    var timeOffset = Math.abs(jsCookie.get('clientTimeOffset'));
    var localTime = (new Date()).getTime();
    if(!sessionExpiry){
        window.console.log("Unknown session sessionExpiry");
        return;
    }
    if (localTime - timeOffset > (sessionExpiry+15000)) { // 15 extra seconds to make sure
        window.location = "/login";
        jsCookie.remove('sessionExpiry');
    } else {
        setTimeout('checkSession()', 10000);
    }
    window.console.log("Session expires in " + ((sessionExpiry+15000) - localTime - timeOffset) + "ms");
}

window.checkSession = checkSession; //Used for recalling via setTimeout

SessionTimeoutCookieFilter.java

public class SessionTimeoutCookieFilter implements Filter {

    private static final Logger LOG = LoggerFactory.getLogger(SessionTimeoutCookieFilter.class);

    @Override
    public void init(FilterConfig config) throws ServletException {
        LOG.info("Initialization SessionTimeoutCookieFilter");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse httpResp = (HttpServletResponse) resp;
        HttpServletRequest httpReq = (HttpServletRequest) req;

        long currTime = System.currentTimeMillis();
        String expiryTime = Long.toString(currTime + httpReq.getSession().getMaxInactiveInterval() * 1000);
        Cookie cookie = new Cookie("serverTime", Long.toString(currTime));
        cookie.setPath("/");
        httpResp.addCookie(cookie);
        if (httpReq.getRemoteUser() != null) {
            cookie = new Cookie("sessionExpiry", expiryTime);
        }
        cookie.setPath("/");
        httpResp.addCookie(cookie);

        filterChain.doFilter(req, resp);
    }

Добавьте фильтр

public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
...
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[]{new SessionTimeoutCookieFilter()};
    }
}

Ответ 4

Чтобы перенаправить на страницу входа после истечения срока действия сеанса, добавьте тег "invalid-session-url" в "управление сеансом" bean в контексте безопасности:

<session-management invalid-session-url="/error-login">
    ....
</session-management>

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

Ответ 5

Это может быть Spring-Security, Spring-MVC или сервлет, автоматический выход из строя невозможен без совершенной логики на стороне клиента.
Рассматриваемая заявка будет иметь оба типа запросов

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

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

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


1. Никаких дополнительных вызовов/запросов не используется для достижения этой цели. с учетом влияния на производительность, если более 10 000 активных пользователей и дополнительные вызовы для достижения автоматического выхода.
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. Настройте атрибуты сеанса для настройки времени ожидания Примечание. Настройте это после создания сеанса. Вы можете реализовать метод sessionCreated HttpSessionListener и установить следующую конфигурацию в соответствии с вашими требованиями.

session.setMaxInactiveInterval(300);

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

4. Добавьте ниже HTML для отображения таймера.
Примечание: его можно переместить на страницу шаблона скрипта автолога, если вы хорошо разбираетесь в CSS. Следовательно, вы можете избежать добавления этого на каждой странице.
Включите загрузчик или добавьте свой собственный 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>

enter image description here

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

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


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

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

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

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


1. Настройка обновления заголовка в ответе http. (Не работает для запросов AJAX)

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