Как реализовать фильтр входа в систему в JSF?

Я хотел бы заблокировать доступ к какой-либо странице, даже если пользователь знает URL-адрес некоторых страниц. Например, /localhost:8080/user/home.xhtml (сначала необходимо выполнить вход), если не зарегистрировано, затем перенаправить на /index.xhtml,

Как это сделать в JSF? Я прочитал в Google, что нужен фильтр, но я не знаю, как это сделать.

2 ответа

Решение

Вам необходимо реализовать javax.servlet.Filter класс, сделать желаемую работу в doFilter() метод и отобразить его на шаблон URL, охватывающий ограниченные страницы, /user/* может быть? Внутри doFilter() Вы должны как-то проверить присутствие вошедшего в систему пользователя в сеансе. Кроме того, вам также необходимо принять во внимание запросы AJAX и ресурсов JSF. AJAX-запросы JSF требуют специального XML-ответа, чтобы JavaScript мог выполнить перенаправление. Запросы ресурсов JSF необходимо пропустить, иначе на вашей странице входа больше не будет CSS / JS / изображений.

Предполагая, что вы /login.xhtml страница, которая сохраняет зарегистрированного пользователя в управляемом компоненте JSF через externalContext.getSessionMap().put("user", user) тогда вы можете получить его через session.getAttribute("user") обычный способ, как показано ниже:

@WebFilter("/user/*")
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.
        }
    }


    // You need to override init() and destroy() as well, but they can be kept empty.
}

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

Если вы используете библиотеку утилит JSF OmniFaces, приведенный выше код может быть уменьшен, как показано ниже:

@WebFilter("/user/*")
public class AuthorizationFilter extends HttpFilter {

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

        boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
        boolean loginRequest = request.getRequestURI().equals(loginURL);
        boolean resourceRequest = Servlets.isFacesResourceRequest(request);

        if (loggedIn || loginRequest || resourceRequest) {
            if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackru.com/q/4194207/157882
                Servlets.setNoCacheHeaders(response);
            }

            chain.doFilter(request, response); // So, just continue request.
        }
        else {
            Servlets.facesRedirect(request, response, loginURL);
        }
    }

}

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

Хотя, конечно, законно использовать простой фильтр сервлетов, существуют альтернативы, такие как

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