Filters

A filter allows web developers to do something before the actual resource is processed. The best example is authentication. Before any .JSP is executed in the application, we want to check whether user has logged in. If not, we want to take user to login page (login.jsp), where user can enter his credentials.

What is a Filter?

A filter is executed before the actual endpoint (such as Servlet, JSP or even a simple HTML page). The following are the main operations that can be performed by a filter:

A filter is a component that exists in the chain and the last link in the chain is the resource actually requested by the user. The following pictures shows that before a request is processed we may execute multiple filters.Each filter sends controls to next filter in the chain. In the process, the last filter sends control to endpoint.

Filter Life Cycle

Filter's life cycle is similar to the life cycle of a Servlet. The following are the important steps in the life cycle.

To understand how to create a filter and use it, let us create an application in Tomcat 4.x with the following directory structure.

c:\tomcat
  |
  |
   ---webapps
         |
         |
          ---- test
                |
                |
                |
                ---- WEB-INF
                      |
                      |
                      ---classes
                      |   |
     	              |   |
                      |   ------- st
                      -- web.xml  |
	                          |
                                  ------ BasicFilter.java

Creating a Simple Filter

Creating a filter involves two steps. First is to create the filter and second is to deploy the filter by modifying web.xml.

First create the following filter which simply displays messages when important events occur.

package st;
import java.io.IOException;

import javax.servlet.*;



public class BasicFilter implements Filter
{

private FilterConfig filterConfig;

 public void init(FilterConfig filterConfig) throws ServletException
 {
  System.out.println("Filter initialized");
  this.filterConfig = filterConfig;
 }
 public void destroy()
 {
  System.out.println("Filter destroyed");
  this.filterConfig = null;
 }
 public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException
 {
   System.out.println("doFilter");
   chain.doFilter(request, response);
 }
}

The class must be placed inside WEB-INF/classes/st directory as it belongs to st package.

Get into st directory and do the following.

  1. Set path and classpath as follows:
    path=c:\jdk1.5.0\bin
    set classpath=.;c:\tomcat\common\lib\servlet.jar
    
  2. Compile BasicFilter.java as follows:
    javac  BasicFilter.java
    

Deploying the Filter

Once a filter is created and compiled then it is to be deployed using web.xml.
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

   <filter>
       <filter-name>Basic Filter</filter-name>
       <filter-class>st.BasicFilter</filter-class>
   </filter>
   
   <filter-mapping>
       <filter-name>Basic Filter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>

</web-app>

Tag filter is used to associate a name with the filter. The filter name is then used in filter-mapping to specify which url-pattern is associated with the filter. In the above example, the filter is invoked whenever any request is made in the application (/*).

When you start Tomcat, you must see a message Filter Initialized as BasicFilter is initialized in test application as you start Tomcat.

Whenever you make a request in test application, you will see a message in Tomcat window.

BasicFilter is just to understand the steps required to create a filter. Now, let us understand how we can implement security using a filter.

Authentication With Filer

The following filter is used to check whether user has logged in. Whenever user makes a request for a .JSP file, the filter is activated. However, filter must not be activated when login.jsp is called as it is used to process the login. Filter checks whether the requested URL is login.jsp, if so it does nothing otherwise it checks whether user has logged in. Session attribute logged indicated whether user has logged or not. We assume attribute logged is set in session in login.jsp during the login process.

package st;

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;


/* checks whether user has logged in.  Session attribute logged indicates whether user has logged or not.
   If session attribute  logged is present, it means user has logged in otherwise send control to login.html.

   This filter must NOT be processed when login.jsp is called. So we check whether the requested URL is login.jsp.
   If so we do nothing in this filter.
*/

public class AuthenticationFilter implements Filter
{

 public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException
 {

   HttpServletRequest  httprequest = (HttpServletRequest)  request;
   HttpServletResponse  httpresponse = (HttpServletResponse) response;


   // do this only when request is NOT for login.jsp

   if ( httprequest.getRequestURI().indexOf("login.jsp") == -1)
   {

      HttpSession  session = httprequest.getSession();
      String  logged =  (String) session.getAttribute("logged");

      if ( logged == null )
      {
         httpresponse.sendRedirect("login.html");
         return;
      }
   }

   // procede if user is authenticated

   chain.doFilter(request, response);
  }

  public void init(FilterConfig filterConfig) throws ServletException
  { }
  public void destroy()
  { }
}

Make sure you create remaining components related to the example such as login.jsp , login.html etc. are created by you.

We need to add filter and filter-mapping entries (as shown below) in web.xml in order to deploy AuthenticationFilter.

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

   <filter>
       <filter-name>Basic Filter</filter-name>
       <filter-class>st.BasicFilter</filter-class>
   </filter>
   <filter>
       <filter-name>Authentication Filter</filter-name>
       <filter-class>st.AuthenticationFilter</filter-class>
   </filter>
   <filter-mapping>
       <filter-name>Basic Filter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
   <filter-mapping>
       <filter-name>Authentication Filter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>

</web-app>

The concept of Filter is very powerful and flexible. Introduced in Servlet 2.3, it can replace tedious process we had to adapt for some of the requirement.

Keep Learning,

P.Srikanth