web-dev-qa-db-ger.com

Wie implementiere ich einen Login-Filter in JSF?

Ich möchte den Zugriff auf einige Seiten blockieren, auch wenn der Benutzer die URL einiger Seiten kennt. Zum Beispiel, /localhost:8080/user/home.xhtml (muss zuerst angemeldet werden) Wenn nicht angemeldet, dann umleiten zu /index.xhtml.

Wie geht das in JSF? Ich habe in Google gelesen, dass ein Filter benötigt wird, aber ich weiß nicht, wie das geht.

47
Valter Silva

Sie müssen die Klasse javax.servlet.Filter implementieren, den gewünschten Job in der Methode doFilter() ausführen und sie einem URL-Muster zuordnen, das die eingeschränkten Seiten abdeckt. /user/* könnte sein? Innerhalb der doFilter() solltest du irgendwie die Anwesenheit des angemeldeten Benutzers in der Sitzung überprüfen. Außerdem müssen Sie JSF-Ajax- und Ressourcenanforderungen berücksichtigen. JSF-Ajax-Anforderungen erfordern eine spezielle XML-Antwort, damit JavaScript eine Umleitung ausführt. JSF-Ressourcenanforderungen müssen übersprungen werden, da Ihre Anmeldeseite sonst keine CSS/JS/Bilder mehr enthält.

Angenommen, Sie haben eine /login.xhtml - Seite, auf der der angemeldete Benutzer über externalContext.getSessionMap().put("user", user) in einer JSF-verwalteten Bean gespeichert ist, dann können Sie diese wie gewohnt über session.getAttribute("user") abrufen Wie unten:

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

Außerdem hat der Filter den Browser-Cache auf gesicherten Seiten deaktiviert, sodass die Schaltfläche "Zurück" des Browsers diese nicht mehr anzeigt.

Falls Sie zufällig die JSF-Hilfsprogrammbibliothek OmniFaces verwenden, kann der obige Code wie folgt reduziert werden:

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

}

Siehe auch:

91
BalusC

Obwohl es natürlich legitim ist, einen einfachen Servlet-Filter zu verwenden, gibt es Alternativen wie

2
Werner Keil