Перенаправление авторизации по истечении сеанса не работает при отправке формы JSF, страница остается прежней

Я использую JSF2. Я реализовал пользовательский сервлет лица следующим образом:

public class MyFacesServletWrapper extends MyFacesServlet {
    // ...
}

при этом я делаю некоторые проверки авторизации и отправляю перенаправление, когда пользователь не вошел в систему:

public void service(ServletRequest request, ServletResponse response) {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    if (...) {
        String loginURL = req.getContextPath() + "/LoginPage.faces";
        res.sendRedirect(loginURL);
    }
}

Это работает, когда пользователь пытается перейти на другую страницу. Однако это не работает, когда форма JSF отправляется с помощью ссылки / кнопки команды JSF. Линия sendRedirect() строка нажата и выполнена, исключение не выдается, но пользователь остается на той же странице. По сути, никаких визуальных изменений нет.

Почему это работает при навигации по страницам, а не при отправке формы?

2 ответа

Решение

Ваша конкретная проблема, скорее всего, вызвана тем, что ссылка / кнопка вашей команды JSF фактически отправляет ajax-запрос, который, в свою очередь, ожидает специальный XML-ответ. Если вы отправляете перенаправление в ответ на запрос AJAX, он просто повторно отправляет запрос AJAX на этот URL. Это, в свою очередь, завершается неудачно без обратной связи, поскольку URL-адрес перенаправления возвращает целую страницу HTML вместо специального ответа XML. На самом деле вы должны возвращать специальный XML-ответ, в котором движку JSF ajax было дано указание изменить текущий window.location,

Но у вас на самом деле большие проблемы: использование неправильного инструмента для работы. Вы должны использовать фильтр сервлетов для работы, а не доморощенный сервлет и, конечно, не тот, который вытесняет FacesServlet кто несет ответственность за все работы JSF.

Предполагая, что вы выполняете вход в систему в компоненте поддержки JSF области запросов / просмотра следующим образом (если вы используете управляемую контейнером аутентификацию, см. Также 2-й пример выполнения аутентификации пользователя в Java EE / JSF с использованием j_security_check):

externalContext.getSessionMap().put("user", user);

Тогда этот стартовый пример фильтра должен сделать:

@WebFilter("/*") // Or @WebFilter(servletNames={"facesServlet"})
public class AuthorizationFilter implements Filter {

    private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
        + "<partial-response><redirect url=\"%s\"></redirect></partial-response>";

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        String loginURL = request.getContextPath() + "/login.xhtml";

        boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
        boolean loginRequest = request.getRequestURI().equals(loginURL);
        boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
        boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));

        if (loggedIn || loginRequest || resourceRequest)) {
            if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackru.com/q/4194207/157882
                response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
                response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
                response.setDateHeader("Expires", 0); // Proxies.
            }

            chain.doFilter(request, response); // So, just continue request.
        }
        else if (ajaxRequest) {
            response.setContentType("text/xml");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
        }
        else {
            response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
        }
    }

    // ...
}

Смотрите также:

.. FacesContext.getCurrentInstance() getExternalContext() перенаправления ("newpage.xhtml"); попробуйте это.... вместо res.sendredirect(cpath).

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