- 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: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.
- 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: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.