How to implement authentication filter for Java web application
- Details
- Written by Nam Ha Minh
- Last Updated on 28 June 2019   |   Print Email
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: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: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:
- How to Create Java Servlet Filter
- How to modify HTTP response using Java Filter
- How to Code Hit Counter for Java web application
Other Java Servlet Tutorials:
- Java Servlet for beginners (XML)
- Java Servlet for beginners (Annotation)
- Java Servlet and JSP Hello World Tutorial with Eclipse, Maven and Apache Tomcat
- How to use Cookies in Java web application
- How to use Session in Java web application
- Java File Upload Example with Servlet
- Java File Download Servlet Example
Comments
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.