Как реализовать фильтр входа в систему в JSF? - PullRequest
47 голосов
/ 12 декабря 2011

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

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

Ответы [ 2 ]

91 голосов
/ 13 декабря 2011

Вам необходимо реализовать класс 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://stackoverflow.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://stackoverflow.com/q/4194207/157882
                Servlets.setNoCacheHeaders(response);
            }

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

}

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

2 голосов
/ 13 декабря 2017

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

...