Spring Security Session Timeout Обработка переадресации вызовов Ajax для входа в систему не работает - PullRequest
1 голос
/ 12 октября 2019

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

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.util.ThrowableAnalyzer;
import org.springframework.security.web.util.ThrowableCauseExtractor;
import org.springframework.web.filter.GenericFilterBean;

public class AjaxTimeoutRedirectFilter extends GenericFilterBean{

    private static final Logger logger = LoggerFactory.getLogger(AjaxTimeoutRedirectFilter.class);

    private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
    private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();

    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    private int customSessionExpiredErrorCode = 901;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        try
        {
            chain.doFilter(request, response);

            logger.debug("Chain processed normally");
        }
        catch (IOException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            Throwable[] causeChain = throwableAnalyzer.determineCauseChain(ex);
            RuntimeException ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);

            if (ase == null)
            {
                ase = (AccessDeniedException) throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
            }

            if (ase != null)
            {
                if (ase instanceof AuthenticationException)
                {
                    throw ase;
                }
                else if (ase instanceof AccessDeniedException)
                {

                    if (authenticationTrustResolver.isAnonymous(SecurityContextHolder.getContext().getAuthentication()))
                    {
                        HttpServletRequest httpReq = (HttpServletRequest) request;

                        logger.info("User session expired or not logged in yet");
                        String ajaxHeader = ((HttpServletRequest) request).getHeader("X-Requested-With");

                        if ("XMLHttpRequest".equals(ajaxHeader))
                        {
                            logger.info("Ajax call detected, send {} error code", this.customSessionExpiredErrorCode);


                            ((HttpServletResponse)response).sendRedirect("/home/login");



                            return;
                        }else
                        {

                            ((HttpServletResponse)response).sendRedirect("/home/login");
                            logger.info("Redirect to login page");
                            return;
                        }
                    }
                    else
                    {
                        this.redirectStrategy.sendRedirect((HttpServletRequest) request, (HttpServletResponse) response,"/home/login");
                        return; 
                    }
                }
            }

        }
    }



    private static final class DefaultThrowableAnalyzer extends ThrowableAnalyzer
    {
        /**
         * @see org.springframework.security.web.util.ThrowableAnalyzer#initExtractorMap()
         */
        protected void initExtractorMap()
        {
            super.initExtractorMap();

            registerExtractor(ServletException.class, new ThrowableCauseExtractor()
            {
                public Throwable extractCause(Throwable throwable)
                {
                    ThrowableAnalyzer.verifyThrowableHierarchy(throwable, ServletException.class);
                    return ((ServletException) throwable).getRootCause();
                }
            });
        }

    }

    public void setCustomSessionExpiredErrorCode(int customSessionExpiredErrorCode)
    {
        this.customSessionExpiredErrorCode = customSessionExpiredErrorCode;
    }
}

Я добавил этот <security:custom-filter ref="ajaxTimeoutRedirectFilter" after="EXCEPTION_TRANSLATION_FILTER"/> и bean-компонент ajaxTimeoutRedirectFilter в файл конфигурации xml, но не работает. При отладке происходит переадресация кода, но перенаправление не перенаправляет на вход в систему.

1 Ответ

0 голосов
/ 13 октября 2019

В качестве состояния ответа на вызов ajax после перенаправления будет 200 вместо 302. Не остается опции для идентификации перенаправления из состояния.

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

Простой способ -
1. Добавьте этот скрытый div на странице входа.

<div style="display:none">LOGIN_PAGE_IDENTIFIER</div>
И на каждой странице JSP (или, если у вас есть какие-либо config.js, которые вы включаете в каждую страницу jsp, добавьте туда код ниже)
<script type="text/javascript">
    $(document).ajaxComplete(function (event, xhr, settings) {
        if(xhr.responseText.indexOf("LOGIN_PAGE_IDENTIFIER") != -1)
            window.location.reload();
    });
</script>


PS :
О вашей озабоченности по поводу вашего AjaxTimeoutRedirectFilter
Если вы получаете статус 901 в ответе ajax, тогда

$(document).ajaxComplete(function (event, xhr, settings) {
    if(xhr.status == 901)
        window.location.reload();
});

добавьте это на каждую свою страницу JSPдолжен решить вашу проблему.

...