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.
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
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.
path=c:\jdk1.5.0\bin set classpath=.;c:\tomcat\common\lib\servlet.jar
javac BasicFilter.java
<?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.
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,