Authorization servlet filter for JSF


(Craig McClanahan should be given all credit for the following content)

There’s a behavior in JavaServer Faces (JSF) technology that can feel a little awkward – the URL shown in the navigator is one page late compared to what is actually showing in the browser. This is by design and, from 30,000 feet, the result of using RequestDispatcher.forward() in the controler. Unless you work for Sun and really want to show implementation details like the /faces context in the URL (JSF rules!), I would suggest hiding the URL altogether.

The other side effect is that it can be tricky to obtain the destination page (vs. the source) page to implement a role filter using servlet filters. Servlet filters are elegant here because they are orthogonal to the application and not linked to JSF APIs. They can implement authentication (is the person logged in?) and authorization (can the person access this required target page?). Although a J2EE 1.3 API specification level (JSP 1.2, Servlet 2.3) should be enough for JSF 1.1, you will need to upgrade to a J2EE 1.4 runtime in order to use new Servlet 2.4 features. This is required to get the destination page to implement the authorization piece of the filtering. So a filter would look like this:


public void doFilter(....) throws ... {
    String
RESTRICTED_PAGE = "/ManagerPage.jsp";
    try {
        // getting the *destintation* page
        String relativePath = request.getServletPath()
               + request.getPathInfo();
        // Trying to access a restricted page
        if ( RESTRICTED_PAGE.equals(relativePath) ) {
            // implement authorization
            ....
            if ( !authorized  ) {
                // not authorized
                resp.sendRedirect("/faces/error.jsp");
            }
        }
       chain.doFilter(request, response);
   }
}


The web.xml deployment descriptor should also be updated to J2EE 1.4 :

<web-app      version="2.4"
                xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                       http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

and have the following filter mapping :

<filter-mapping>
    <filter-name>Role Filter</filter-name>
    <url-pattern>/\*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

If you can’t use a J2EE 1.4 runtime (again, only required by the filter, not by the JSF application per se), the alternate strategy would be to “defensively” code the authorization logic in each managed-bean page constructor. In that case you could avoid code replication by having an indirection call from each page constructor to a session- or application-scope managed bean with the logic, but you’re still responsible for calling this authorization method and the filter still sounds like a better approach.

All this information is applicable and has been tested on Java Studio Creator which by default uses Sun Application Server 8 (a free J2EE 1.4 implementation). An article on Sun Developer Network on this “feature” and focusing on Sun Java Studio Creator should be made available in the future.

Author: alexismp

Google Developer Relations in Paris.

7 thoughts on “Authorization servlet filter for JSF”

  1. Hi Alexis,
    you should look towards jGuard (www.jguard.net) which provides authentication and authorization based on JAAS for j2ee webapps.
    it is based on a servlet filter, and provides a taglib to protect fragment of pages.
    it includes other features like role inheritance, ocsp and CRL support(useful for x509 certificate authentication) and so on…
    a war is provided with the distribution for a quick test.
    cheers,
    Charles(jGuard team).

  2. Hi Alexis!
    I’ve tried out the way you implemented that filter but have some trouble when using MyFaces together with tiles (using the TilesViewHandler). I haven’t fully examined the context in which MyFaces, tiles and the filter are (not) working together. Do you or any of the readers allready have experimented with that combination? I would be deeply grateful for your ideas on making this combination work.

  3. I use creator 2.
    I have a page with a hyperlink which is linked to a protected page.
    The protected page is displayed even for users who are not autorized. In the HTTP monitor I don’t see any GET (or any other request) to this protected page, even when this page is displayed in my browser. So, the authorization filter which tests getPathInfo, does not work and I cannot protect this page.
    I certainly does not understand a basic thing. Can someone help me?

  4. Have you tried the JAAS sample application that comes with Creator 2? It’s very similar and essentially a better polished version of this sample.

  5. I have found my error: I used navigation with the hyperlink instead of putting the “url” property of the hyperlink.
    With the navigation, the hyperlink works but it does not use a GET to obtain the protected page (hence my problem with getPathInfo).

Comments are closed.