FullAjaxExceptionHandler не показывает страницу ошибки с истекшим сроком сеанса на кнопке ajax

Я реализовал Omnifaces FullAjaxExceptionHandler, но проблема в том, что он не работает с запросами ajax. После истечения срока действия сеанса, когда я нажимаю кнопку без ajax, он работает хорошо. Он перенаправляет пользователя на пользовательскую страницу ошибки. Но если кнопка использует ajax, она ничего не делает. Страница просто зависает.

Изменить: я изменил ActionListener на Action и все так же.

Edit2: это не дает ошибки. Ни выходные данные Apache Tomcat, ни журнал Apache Tomcat.

введите здесь описание изображения

вот моя весенняя охрана;

<http auto-config='true' use-expressions="true">
    <intercept-url pattern="/login" access="permitAll"/>
    <intercept-url pattern="/ajaxErrorPage" access="permitAll"/>
    <intercept-url pattern="/pages/*" access="hasRole('admin')" />
    <intercept-url pattern="/j_spring_security_check" access="permitAll"/>        
    <logout logout-success-url="/login.xhtml" />
    <form-login login-page="/login.xhtml"
                login-processing-url="/j_spring_security_check"                                                       
                default-target-url="/pages/index.xhtml"
                always-use-default-target="true"                                                        
                authentication-failure-url="/login.xhtml"/>
</http>

person hellzone    schedule 25.06.2013    source источник
comment
Каково содержание ответа ajax?   -  person BalusC    schedule 25.06.2013
comment
‹p:menuitem value=открыть новую вкладку action=#{myController.openNewTab()} update=:contentPanel/› У меня есть элемент меню, и когда пользователь щелкает этот элемент меню, будет отображаться вкладка в представлении вкладок. Кстати каждая вкладка включает в себя разные страницы. Это как Гугл Хром. У пользователя есть несколько закладок, и если он щелкнет какую-либо закладку, приложение откроет ее страницу в новой вкладке.   -  person hellzone    schedule 25.06.2013
comment
Каково содержание ответа ajax? Нажмите F12 в Chrome и проверьте раздел Сеть, чтобы увидеть его.   -  person BalusC    schedule 25.06.2013
comment
@BalusC я добавил как картинку.   -  person hellzone    schedule 25.06.2013
comment
Итак. Ответ ajax - это перенаправление 302? У вас есть собственный фильтр входа в систему, который выполняет response.sendRedirect(), когда пользователь не вошел в систему или около того?   -  person BalusC    schedule 25.06.2013


Ответы (2)


Вы отправляете синхронное перенаправление в качестве ответа на запрос ajax (ответ HTTP 302, используя, например, response.sendRedirect()). Это неправильно. Механизм JavaScript ajax обрабатывает ответ 302 как новое место назначения для повторной отправки запроса ajax. Однако это, в свою очередь, возвращает простую ванильную HTML-страницу вместо XML-документа с инструкциями, какие части страницы обновлять. Это сбивает с толку, и поэтому перенаправленный ответ полностью игнорируется. Это точно объясняет симптомы, с которыми вы столкнулись.

Та же самая проблема также задается и дается ответ в следующих тесно связанных вопросах:

По сути, вам нужно каким-то образом проинструктировать Spring Security выполнить следующую условную проверку:

if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
    // JSF ajax request. Return special XML response which instructs JavaScript that it should in turn perform a redirect.
    response.setContentType("text/xml");
    response.getWriter()
        .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
        .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", loginURL);
} else {
    // Normal request. Perform redirect as usual.
    response.sendRedirect(loginURL);
}

Однако я не являюсь пользователем Spring, и мне не интересно его использовать, и поэтому я не могу дать более подробный ответ, как выполнить эту проверку в Spring Security. Однако я могу сказать, что у Apache Shiro точно такая же проблема, которая объясняется и решается в этой статье блога: Сделать Shiro JSF Ajax совместимым.

person BalusC    schedule 25.06.2013
comment
Что вы подразумеваете под loginURL? когда я устанавливаю /login.xhtml, приложение пытается открыть localhost:8080/login.xhtml и выдает не найдена ошибка. Когда я устанавливаю /myApp/login.xhtml, он говорит, что на этой странице слишком много ошибок перенаправления. Вы хоть представляете, что происходит? - person hellzone; 26.06.2013
comment
Должно быть request.getContextPath() + "/login.xhtml". Что касается ошибки слишком большого количества перенаправлений, это означает, что она перенаправляется в бесконечном цикле. По-видимому, вы также перенаправляете на login.xhtml, когда запрашивается сам login.xhtml. Затем вы не должны перенаправлять на login.xhtml, а продолжить запрос на chain.doFilter(request, response). Этот ответ близок к тому, что вам, вероятно, нужно: stackoverflow.com/a/14582031 - person BalusC; 26.06.2013
comment
проблема в том, что когда я запускаю приложение, request.getRequestURI() поставляется со строкой /myApp/, а не с /myApp/login.xhtml. Немного запутанно - person hellzone; 26.06.2013
comment
Кажется, вы просто добавляете фильтр сервлета вместо перенастройки Spring Security. В основном вам нужно изменить конфигурацию/логику Spring Security. К сожалению, это не просто вопрос добавления фильтра сервлета. Я рекомендую повторно задать вопрос в следующем контексте: как изменить способ перенаправления Spring Security запроса на страницу входа? Мне нужно вернуть ответ XML на запрос ajax вместо ответа 302. - person BalusC; 26.06.2013
comment
Я решил проблему, но все еще не понимаю, что происходит позади :D в любом случае, теперь это работает. Я изменил несколько строк из stackoverflow.com/a/14582031; логическое значение loginRequest = (request1.getRequestURI().equals(request1.getContextPath() + /)) || (request1.getRequestURI().equals(loginURL)); - person hellzone; 26.06.2013

В файле spring-security (в архиве Spring Security)

<beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>

<!-- redirection strategy -->
<beans:bean id="jsfRedirectStrategy" class="com.mycompany.JsfRedirectStrategy">
    <beans:property name="invalidSessionUrl" value="/login.xhtml" />
</beans:bean>

<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
    <beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
    <beans:property name="invalidSessionStrategy" ref="jsfRedirectStrategy" />
</beans:bean>

<http auto-config='true' use-expressions="true">
    <intercept-url pattern="/login" access="permitAll"/>
    <intercept-url pattern="/ajaxErrorPage" access="permitAll"/>
    <intercept-url pattern="/pages/*" access="hasRole('admin')" />
    <intercept-url pattern="/j_spring_security_check" access="permitAll"/>        
    <logout logout-success-url="/login.xhtml" />
    <form-login login-page="/login.xhtml"
            login-processing-url="/j_spring_security_check"                                                       
            default-target-url="/pages/index.xhtml"
            always-use-default-target="true"                                                        
            authentication-failure-url="/login.xhtml"/>

     <!-- custom filter -->
    <custom-filter ref="sessionManagementFilter"  before="SESSION_MANAGEMENT_FILTER" />

</http>

Пользовательская стратегия перенаправления (La estrategia de redirection personalizada)

public class JsfRedirectStrategy implements InvalidSessionStrategy
{

    private static final String FACES_REQUEST = "Faces-Request";

    private String invalidSessionUrl;

    public void setInvalidSessionUrl(String invalidSessionUrl) {
        this.invalidSessionUrl = invalidSessionUrl;
    }

    public String getInvalidSessionUrl() {
       return invalidSessionUrl;
    }



    @Override
    public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {



        String contextPath = request.getContextPath();
        String urlFinal = contextPath+invalidSessionUrl;




        if ("partial/ajax".equals(request.getHeader(FACES_REQUEST))) {
            // with ajax
            response.setContentType("text/xml");
            response.getWriter()
                .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
                .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", urlFinal);
        } else {

            // not ajax
            request.getSession(true);
            response.sendRedirect(urlFinal);

        }

   }

работай на меня.

person Alvaro C.    schedule 12.02.2014