3

I am using following filter to control access to all pages in JSF 2.0 using GlassFish as application server. The problem is that with this code although filter works fine and user are redirected to log.xhtml if they try to acess anyother page directly but the login.xhtml does not look good (no colored image displayed and while page shape changed) as it should be. However if i remove the sendRedirect statement and replace it with chain.doFilter statement, then the page displays in the same way as it should be looking nice and good however filtering does not work obviously. How can I fix this problem?

LoggingFilter.java

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {   
    HttpServletRequest req = (HttpServletRequest) request;
    LoginBean auth = (LoginBean) req.getSession().getAttribute("loginBean");




    if ((auth != null && auth.isLoggedIn()) || req.getRequestURI().endsWith("/login.xhtml")) {
        // User is logged in, so just continue request.
        HttpServletResponse httpResponse = (HttpServletResponse)response;
        httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        httpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        httpResponse.setDateHeader("Expires", 0); // Proxies.
        chain.doFilter(request, response);
    } else {
        // User is not logged in, so redirect to index.
        HttpServletResponse res = (HttpServletResponse) response;
        res.sendRedirect(req.getContextPath() + "/faces/login.xhtml");
        //FacesContext.getCurrentInstance().getExternalContext().dispatch("/login.xhtml");
        //chain.doFilter(request, response);
    }
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Moazzam
  • 397
  • 1
  • 8
  • 23

1 Answers1

10

This filter also redirects all requests on CSS/JS/image files to the login page. The browser end up getting a response containing some HTML code representing the login page instead of the concrete CSS/JS/image content it requested for and hence the browser fails applying the necessary look'n'feel.

Provided that you're 100% utilizing JSF resource management (<h:outputStylesheet>, etc) and thus they are all covered by /javax.faces.resource/* URIs, rewrite your filter as follows:

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

    LoginBean auth = (session != null) ? session.getAttribute("loginBean") : null;
    String loginURL = request.getContextPath() + "/faces/login.xhtml";

    boolean loggedIn = auth != null && auth.isLoggedIn();
    boolean loginRequest = request.getRequestURI().equals(loginURL);
    boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + "/faces" + ResourceHandler.RESOURCE_IDENTIFIER);

    if (loggedIn || loginRequest || resourceRequest)) {
        if (!resourceRequest) {
            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);
    } else {
        response.sendRedirect(loginURL);
    }
}

Note that no-cache headers should not be set on resource requests, otherwise you defeat the benefit of the browser cache on CSS/JS/image files.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks. By using this code, images and css styles are being applied successfully and page is looking great now. But i am using rich:panel and a4j:commandButton on the login page, this panel and button is not displaying correctly. How can i stop redirecting request for these resources to login page. – Moazzam Jan 26 '13 at 05:17
  • 1
    The issue is resolved by adding following statement: boolean richRequest = request.getRequestURI().startsWith(request.getContextPath() + "/faces/rfRes");
    if (loggedIn || loginRequest || resourceRequest || richRequest) { chain.doFilter(request, response); } else { response.sendRedirect(loginURL); }
    – Moazzam Jan 26 '13 at 06:38
  • The issue is resolved by adding following statement: boolean richRequest = request.getRequestURI().startsWith(request.getContextPath() + "/faces/rfRes"); if (loggedIn || loginRequest || resourceRequest || richRequest) { chain.doFilter(request, response); } else { response.sendRedirect(loginURL); } – Moazzam Jan 26 '13 at 06:44