In Java web development, Filters can be used to implement authentication feature for the application besides the primary functions login and logout. A typical scenario is when a user tries to access a page that requires authentication and if he is not logged in, the application should display the login page. And after the user has been authenticated successfully, he is allowed to access any pages that require authentication.

You can write code in Java Servlets and JSPs to implement such kind of authentication, but it is inefficient because you have to insert the authentication code for every page, which is time-consuming, increases duplicate code and makes the code difficult to maintain.

Java Filters come as a perfect solution, as the primary purpose of filters is to inspect the request and transform the response. You need to write code for only a filter class and don’t have to touch any JSP pages.

Therefore, this tutorial helps you understand and use filters to implement authentication feature for your website.

 

1. Code Authentication Filter for Admin Module

Typically, all pages in the website’s admin module require authentication except the login page. Before creating an authentication filter, suppose that you have done the login and logout functions with the following details:

- All the pages in the admin are under ContextPath/admin directory. Hence the URL of the admin’s homepage is ContextPath/admin/

- The URL of the login page is ContextPath/admin/login.jsp

- The URL of the Java servlet that handles login request is ContextPath/admin/login

- The name of the attribute in the session is adminUser- this attribute is set right after an admin user has been logged in successfully.

We expect the following behaviors:

- If the user is not logged in, he will be redirected to the login page for all requests. This prevents unauthorized access to admin pages.

- If the user is logged in, and the request is for login, he will be redirected to the admin’s homepage. This prevents the user from logging in more than one time if he has not logged out.

- If the user is logged in, and the request is not for login, continue the filter chain - allow the request to reach the destination.

The following activity diagram describes the workflow which an authentication filter will process for every request:

Admin Authentication Filter Activity Diagram



And create a Java filter class with the following code:

package net.codejava.admin;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * This Java filter demonstrates how to intercept the request
 * and transform the response to implement authentication feature.
 * for the website's back-end.
 *
 * @author www.codejava.net
 */
@WebFilter("/admin/*")
public class AdminAuthenticationFilter implements Filter {

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

		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpSession session = httpRequest.getSession(false);

		boolean isLoggedIn = (session != null && session.getAttribute("adminUser") != null);

		String loginURI = httpRequest.getContextPath() + "/admin/login";

		boolean isLoginRequest = httpRequest.getRequestURI().equals(loginURI);

		boolean isLoginPage = httpRequest.getRequestURI().endsWith("login.jsp");

		if (isLoggedIn && (isLoginRequest || isLoginPage)) {
			// the admin is already logged in and he's trying to login again
			// then forwards to the admin's homepage
			RequestDispatcher dispatcher = request.getRequestDispatcher("/admin/");
			dispatcher.forward(request, response);

		} else if (isLoggedIn || isLoginRequest) {
			// continues the filter chain
			// allows the request to reach the destination
			chain.doFilter(request, response);

		} else {
			// the admin is not logged in, so authentication is required
			// forwards to the Login page
			RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
			dispatcher.forward(request, response);

		}

	}

	public AdminLoginFilter() {
	}

	public void destroy() {
	}

	public void init(FilterConfig fConfig) throws ServletException {
	}

}
As you can see, this filter intercepts all the requests having the URL pattern /admin/*, and the code in the doFilter() method implements the workflow above.

 

2. Code Authentication Filter for Website's Front-End Pages

Typically, pages in a website’s front-end have public access for all visitors, except some private pages that require authentication like customer profile details.

Before creating an authentication filter, suppose that you have done the login and logout functions with the following details:

- All the pages are directly under ContextPathdirectory. Hence the URL of the website’s homepage is ContextPath/

- The URL of the login page is ContextPath/login.jsp

- The URL of the Java servlet that handles login request is ContextPath/login

- The name of the attribute in the session is customerUser- this attribute is set right after a customer user has been logged in successfully.

We expect the following behaviors:

- By default, pages are accessible. No authentication is required.

- If the customer is not logged in, and trying to access a page that requires authentication, he will be redirected to the login page. This prevents unauthorized access to private pages.

- If the customer is logged in, and the request is for login, he will be redirected to the website’s homepage. This prevents the customer from logging in more than one time if he has not logged out.

- If the customer is logged in, and the request is not for login, continue the filter chain - allow the request to reach the destination.

The following activity diagram describes the workflow which an authentication filter will process for every request:

FrontEnd Authentication Filter Activity Diagram

And the following is sample code of a Java filter that implements the workflow above:

package net.codejava.frontend;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * This Java filter demonstrates how to intercept the request
 * and transform the response to implement authentication feature
 * for the website's front-end.
 *
 * @author www.codejava.net
 */
@WebFilter("/*")
public class FrontEndAuthenticationFilter implements Filter {
	private HttpServletRequest httpRequest;

	private static final String[] loginRequiredURLs = {
			"/view_profile", "/edit_profile", "/update_profile"
	};

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

		String path = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());

		if (path.startsWith("/admin/")) {
			chain.doFilter(request, response);
			return;
		}

		HttpSession session = httpRequest.getSession(false);

		boolean isLoggedIn = (session != null && session.getAttribute("customerUser") != null);

		String loginURI = httpRequest.getContextPath() + "/login";
		boolean isLoginRequest = httpRequest.getRequestURI().equals(loginURI);
		boolean isLoginPage = httpRequest.getRequestURI().endsWith("login.jsp");

		if (isLoggedIn && (isLoginRequest || isLoginPage)) {
			// the user is already logged in and he's trying to login again
			// then forward to the homepage
			httpRequest.getRequestDispatcher("/").forward(request, response);

		} else if (!isLoggedIn && isLoginRequired()) {
			// the user is not logged in, and the requested page requires
			// authentication, then forward to the login page
			String loginPage = "/login.jsp";
			RequestDispatcher dispatcher = httpRequest.getRequestDispatcher(loginPage);
			dispatcher.forward(request, response);
		} else {
			// for other requested pages that do not require authentication
			// or the user is already logged in, continue to the destination
			chain.doFilter(request, response);
		}
	}


	private boolean isLoginRequired() {
		String requestURL = httpRequest.getRequestURL().toString();

		for (String loginRequiredURL : loginRequiredURLs) {
			if (requestURL.contains(loginRequiredURL)) {
				return true;
			}
		}

		return false;
	}

	public CustomerLoginFilter() {
	}

	public void destroy() {
	}

	public void init(FilterConfig fConfig) throws ServletException {
	}

}
As you can see, this filter intercepts all the requests coming to the website with the URL pattern/* - this means the requests coming to the admin section (URL patter /admin/*) are also going through this filter, so we need to exclude such requests with the following code at the beginning of the doFilter() method:

String path = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());

if (path.startsWith("/admin/")) {
	chain.doFilter(request, response);
	return;
}
Declare the URLs of the pages that require authentication in an array like this:

private static final String[] loginRequiredURLs = {
		"/view_profile", "/edit_profile", "/update_profile"
};
And the following method checks if the current request requires authentication or not:

private boolean isLoginRequired() {
	String requestURL = httpRequest.getRequestURL().toString();

	for (String loginRequiredURL : loginRequiredURLs) {
		if (requestURL.contains(loginRequiredURL)) {
			return true;
		}
	}

	return false;
}
That’s some sample code that helps you understand how to implement authentication filters for a Java web application. I also apply the code in this tutorial in my Java Servlet, JSP and Hibernate course. Hope you found this tutorial helpful.

 

Related Tutorials:

 

Other Java Servlet Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Add comment

   


Comments 

#7marcello2021-06-20 13:56
Excellent post! Thank you very much!
Quote
#6Minh Duc2021-03-19 04:28
blog của anh hay quá
Quote
#5Raj2020-10-07 23:07
love you guy.. this proved to be very much helpful to me
Quote
#4Patric Enderson2020-03-16 11:30
Ótimo conteudo, vou comprar o curso da Udemi para complementar meus estudos
Quote
#3Amber2019-11-18 02:10
Hii Nam Ha Minh,
i'm facing issue with browse back button after logout. i'm using cache control code to prevent this but this is not working when i'm using post request. please Help.
Quote