web-dev-qa-db-fra.com

Comment implémenter un filtre de connexion dans JSF?

Je voudrais bloquer l'accès à certaines pages même si l'utilisateur connaît l'url de certaines pages. Par exemple, /localhost:8080/user/home.xhtml (devez d'abord vous connecter) s'il n'est pas connecté, redirigez vers /index.xhtml.

Comment cela dans JSF? J'ai lu dans Google qui avait besoin d'un filtre, mais je ne sais pas comment le faire.

47
Valter Silva

Vous devez implémenter la classe javax.servlet.Filter , faire le travail souhaité dans la méthode doFilter() et le mapper sur un modèle d'URL couvrant les pages restreintes, /user/* peut être? Dans la doFilter(), vous devez vérifier la présence de l'utilisateur connecté dans la session. De plus, vous devez également prendre en compte JSF ajax et les demandes de ressources. Les requêtes ajax JSF nécessitent une réponse XML spéciale pour permettre à JavaScript d'effectuer une redirection. Les demandes de ressources JSF doivent être ignorées, sinon votre page de connexion n'aura plus d'images CSS/JS /.

En supposant que vous avez une page /login.xhtml Qui stocke l'utilisateur connecté dans un bean géré JSF via externalContext.getSessionMap().put("user", user), vous pouvez l'obtenir via session.getAttribute("user") de la manière habituelle comme ci-dessous:

@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.
}

De plus, le filtre a également désactivé le cache du navigateur sur la page sécurisée, de sorte que le bouton de retour du navigateur ne les affichera plus.

Si vous utilisez la bibliothèque d'utilitaires JSF OmniFaces , le code ci-dessus peut être réduit comme ci-dessous:

@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);
        }
    }

}

Voir également:

91
BalusC

Bien qu'il soit bien sûr légitime d'utiliser un simple filtre de servlet, il existe des alternatives comme

2
Werner Keil