August 27, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Securing J2EE Applications with a Servlet Filter

  • February 3, 2005
  • By Michael Klaene
  • Send Email »
  • More Articles »

Web applications oftain contain both public and private resources. It is necessary to ensure that those key areas that are restricted to the public remain off limits to even the craftiest of users. This is a common problem and there are many different solutions. In this article, I will show how a Servlet Filter can serve as a simple, unobtrusive agent that will help to safeguard data when developing J2EE web applications.

A Few Options

When discussing the topic of security, there are two main categories to consider. Authentication refers to verifying a certain user is in fact who they say they are. Authentication is handled typically via a username and password login. For most sites, a login page utilizes SSL (Secure Socket Layer) over HTTP (Hyper Text Transfer Protocol). Once authentication is complete, you need to perform authorization. Authorization is concerned with ensuring that what a user accesses conforms to their permission set. In other words, they should only see what they are authorized to see.

Along with many third-party tools, J2EE provides some built-in support for security. In the deployment descriptor of an application (web.xml), for example, you can declaratively configure an application for authentication and authorization (see options available under the <security-constraint> element). For in-depth information on how to use these features, consult the Java Servlet specification. One potential problem with this approach is that implementing some of these features also requires actions specific to a Servlet container, making them not entirely portable. Another option for security is the Java Authentication and Authorization Service (JAAS). JAAS consists of APIs to authenticate and authorize in a pluggable, platform-neutral fashion. JAAS is a bit newer and its use is not as widespread as those previously mentioned.

Of course, coding a solution yourself is always an option too. This is not always desirable, depending on the complexity of the problem you are dealing with. However, if your application has rather unique or complex security requirements, you will probably require a custom solution. Below, I will demonstrate how Java Servlet Filters can help craft a solution that works across Servlet containers.

Filter Review

Servlet Filters were introduced in version 2.3 of the Java Servlet specification. If you are completely new to Filters, I suggest reading about them here. I will attempt a high-level overview now. Read about the Intercepting Filter design pattern to better understand the problem Filters try to address.

A Servlet Filter object implements an interface that specifies three methods: init, doFilter, and destroy. The first and the last allow for custom processing at the beginning and end of the object's life cycle. To enable a Filter to initialize itself, an instance of FilterConfig is passed to its init method. The most important method for a Filter object is doFilter. This is where the Filter does its job. It accepts objects of type ServletRequest and ServletResponse (which usually need to be cast to their HTTP versions: HttpServletRequest and HttpServletReponse), and a FilterChain object that contains a 'chain' of Filters to execute (if any) after the current Filter finishes its work.

So how does a Filter object execute? A Filter is specified in the web.xml file inside the <filter> element, along with a corresponding <filter-mapping> that maps a Filter to a request pattern. When this pattern matches a request URI, doFilter on the Filter object is invoked. This allows you, the developer, to intercept the normal application flow and perform whatever tasks you deem necessary. These tasks commonly include logging, compression of response data, and in our case, enforcing application security.

An Authorization Filter

For the purposes of this article, I will assume that the authentication piece of the puzzle has been solved, either custom either by programming or using the declarative support the Servlet specification provides. I will focus on performing authorization for the application. For this, you will use a Filter object. In fact, a Servlet Filter could help solve the authentication problem as well (and handle other security-related tasks, such as storing number of login attempts, locking accounts, and so forth.).

The fictitious application includes public resources, resources for intranet users, and resources that should be accessed only by an administrator. As a result, you need to intercept requests to verify that a user's role or roles allows them to go where they are attempting to go. The Filter intercepts the requests, then, to achieve a clean separation of concerns, invokes a method on the Java class that actually performs the work. There are three objects to look at—an interface, its default implementation, and a Filter object. You'll start with the interface.

The Java interface used for authorization is called, appropriately, AuthorizationManager.

package examples;

/**
 * Manages authorization to the system.
 *
 * @author Michael Klaene
 */
public interface AuthorizationManager {

     public boolean isUserAuthorized(User user,String uri);

}

AuthorizationManager specifies a lone method, public boolean isUserAuthorized(User user,String uri). Method isUserAuthorized accepts a User object, presumably stored in the current HttpSession, and the request URI. It returns true if that user is authorized to view the resource, false otherwise.

A Servlet Filter, AuthorizationFilter, will obtain a reference to an object of type AuthorizationManager and invoke its method. The resources for users and an administrator have been grouped in a subfolder entitled 'restricted'. The following web.xml entries are required for AuthorizationFilter's doFilter method to be invoked each time a 'restricted' resource is requested:

<!--Servlet Filter that handles site authorization.-->
<filter>
     <filter-name>AuthorizationFilter</filter-name>
     <filter-class>examples.AuthorizationFilter</filter-class>
     <description>This Filter authorizes user access to application
                  components based upon request URI.</description>
     <init-param>
        <param-name>error_page</param-name>
        <param-value>../../error.jsp</param-value>
     </init-param>
</filter>

<filter-mapping>
     <filter-name>AuthorizationFilter</filter-name>
     <url-pattern>/restricted/*</url-pattern>
</filter-mapping>
Note: You are configuring your Filter by using an initialization parameter called 'error-page'. A FilterConfig object provides this value in AuthorizationFilter's init method. It tells the Filter where to redirect authorization failures:
private String errorPage;

/**Filter should be configured with an system error page.*/
public void init (FilterConfig FilterConfig) throws ServletException {
       if (FilterConfig != null) { 
           errorPage = FilterConfig.getInitParameter("error_page");
       }

Here is the code for doFilter:

public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
       throws ServletException, IOException {
      if(errorPage == null) {
         returnError(request,response,"AuthorizationFilter not
                     properly configured! Contact Administrator.");
      }

      HttpSession session =
          ((HttpServletRequest)request).getSession(false);
      User currentUser = (User)session.getAttribute("user");

      if (currentUser == null) {
          returnError(request,response,"User does not exist in
                      session!");
      }
      else {
          //Get relevant URI.
          String URI = ((HttpServletRequest)request).getRequestURI();

          //Obtain AuthorizationManager singleton from Spring
          //ApplicationContext.
          ApplicationContext ctx =
              WebApplicationContextUtils.getWebApplicationContext(
              session.getServletContext());
          AuthorizationManager authMgr =
              (AuthorizationManager)ctx.getBean("AuthorizationManager");

          //Invoke AuthorizationManager method to see if user can
          //access resource.
          boolean authorized = authMgr.isUserAuthorized(currentUser,URI);
          if (authorized) {
              chain.doFilter(request,response);
          }
          else {
              returnError(request,response,"User is not authorized
                          to access this area!");
          }
      }
}

The top half of doFilter is concerned with checking that the necessary variables are present. The error page should have been stored upon initialization. Also, in this application, a User object should exist in the current session if authentication was performed. A private utility method (returnError) is used to forward to the designated error page with the relevant error text. The remaining code obtains the current URI requested and passes it, along with the User object, to the isUserAuthorizedMethod on an instance of AuthorizationManager. If authorized, the request is forwarded on (possibly to another Filter, if more than one was mapped to this request).





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel