Tuesday, January 24, 2012

Filter Chains

You can specify multiple filters to be called before a Servlet executes.
The filters are then called one after another as a chain.

After any filter executes, it must pass the control to the next filter in the chain by calling chain.doFilter().

If it does not call chain.doFilter(), the execution will end at that point and the Servlet will never be executed.

The Servlet is the last link in the chain, so it will only be executed when the last filter in the chain calls chain.doFilter()

The exact sequence in which the filters get chained follows rules specified in the Servlet specification. So if your filters are order sensitive, you should make sure you have chained them the right way.

Let us see an example, by adding a second filter to our previous example.

Create a new filter class called SecurityFilter.java in org.confucius.
This filter will assign an "access" level to the request depending on which IP address the request came from.

Here is what it looks like:
 package org.confucius;  

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class SecurityFilter implements Filter {

@Override
public void init(FilterConfig arg0) throws ServletException {
}

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

if (request.getRemoteAddr().equalsIgnoreCase("121.23.132.12"))
request.setAttribute("access", "PRIVILEGED");
else
request.setAttribute("access", "REGULAR");

chain.doFilter(request, response);
}

@Override
public void destroy() {
}

}



Let us update the web.xml to use this filter, for _any_ URL:
 <web-app>   
<filter>
<filter-name>security</filter-name>
<filter-class>org.confucius.SecurityFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>security</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>empty_input</filter-name>
<filter-class>org.confucius.InputCheckFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>empty_input</filter-name>
<url-pattern>/register</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.confucius.HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>

</web-app>



Let us also update our Confirm.jsp so we can see that the access is set correctly:
 <html>   
<head>
<%@ page import="org.confucius.User" %>
</head>
<body>
<% User user = (User) request.getAttribute("user"); %>
Confirmation: Registration accepted for <%out.println(user.getFirstName() + " " + user.getLastName());%>
<br/>
Access Level: <% out.println(request.getAttribute("access"));%>
</body>
</html>


If you now build and deploy HelloWorld.war and browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

you will see the access level along with the confirmation.

No comments: