o7planning

Create a simple Login application and secure pages with Java Servlet Filter

  1. Why is security used?
  2. Concept of Role and Principal
  3. Security with Servlet Filter
  4. The goal of example
  5. Create Application
  6. UserAccount & DataDAO
  7. SecurityConfig & SecurityUtils
  8. SecurityFilter
  9. Home Page, Login, Logout
  10. Pages must be logged in

1. Why is security used?

Security is an important aspect of an application with transport of important data on the Internet.
Authentication
Authentication is the process by which users' access privileges are verified prior to their entering a Website's protected area. There are two major authentication approaches: basic authentication and form-based authentication.
Basic Authentication
For basic authentication, a user can access every page completely normally. For the pages requesting security, a window will display for the user to enter his/her username/password. The username/password information will be bundled up to send with the request to Server.
When the user enters a path on browser, and press Enter to request a page. A "User Agent" information is created and sent with the request. Normally, this information includes the user's browser information, operating system information. In case of basic authentication, the username/password information is bundled within the "User Agent".
In this post, I don't mention basic authentication in details.
Form-based Authentication
Most websites use Form-based Authentication. A website allows the user to access every common page without asking for a password. However, if the user visits a protected page, it will redirect to a login page.
In this lesson, I will detail the usage of a Servlet Filter to keep secret Java Web application.

2. Concept of Role and Principal

In security, there are 2 important concepts such as Principal and Role.
Role
Role is a set of permissions for an application.
For simplicity, I give an example, the ABC application has 2 roles of "EMPLOYEE" and "MANAGER".
  • The "EMPLOYEE" role is allowed to use sales functions and customer's information creation function.
  • The "MANAGER" role is allowed to use employee management functions and see revenue reports.
Principal
Principal can be temporarily understood as a "Subject" after logging into a system. It is entitled to do something in the system. An "Subject" can have one or more roles. This depends on the permissions of application for each different user account.

3. Security with Servlet Filter

In the Java Servlet application, a Servlet Filter is specially used to handle security. It is usually called Security Filter.
Below are the operation principles of the Security Filter.
When the user accesses a protected page, the Security Filter will test it. If the user is not logged in, the user's request will be redirected to the login page.
If the user has accessed successfully, a Principal object is created. It brings the user's information, including roles.
If the user has successfully logged in before, and accessed to a protected page. The Security Filter will check if the user's roles are appropriate to access this page or not. If it is invalid, it will show the user a page informing Access denied.

4. The goal of example

This is the structure of application which we will perform:
The application includes 2 roles such as EMPLOYEE and MANAGER.
  1. The EMPLOYEE role allows accessing the 2 pages such /userInfo and /employeeTask
  2. The MANAGER role allows accessing the 2 pages such as /userInfo and /managerTask.
All other pages in the application don't request to access.
There are 2 users such as employee1 and manager1.
  • The employee1 is assigned the role of EMPLOYEE
  • The manager1 is assigned both MANAGER and EMPLOYEE roles.
The user can access all non-protected pages normally. However, if the user visits a protected ABC page, it will redirect to the login page. The User log in successfully, two situations will occur:
  • The application will redirect to the ABC page after logging in successfully, if userName has suitable role.
  • The application will display an Access Denied information if userName has unappropriate role.

5. Create Application

On Eclipse, create a "Dynamic Web Project" called SecurityWebApp, and configure so that it can run on Tomcat Server. I will not detail the steps to do this, you can refer to the following lesson:

6. UserAccount & DataDAO

UserAccount class represents for the user of application.
UserAccount.java
package org.o7planning.securitywebapp.bean;

import java.util.ArrayList;
import java.util.List;

public class UserAccount {
   public static final String GENDER_MALE = "M";
   public static final String GENDER_FEMALE = "F";

   private String userName;
   private String gender;
   private String password;

   private List<String> roles;

   public UserAccount() {

   }

   public UserAccount(String userName, String password, String gender, String... roles) {
      this.userName = userName;
      this.password = password;
      this.gender = gender;

      this.roles = new ArrayList<String>();
      if (roles != null) {
         for (String r : roles) {
            this.roles.add(r);
         }
      }
   }

   public String getUserName() {
      return userName;
   }

   public void setUserName(String userName) {
      this.userName = userName;
   }

   public String getGender() {
      return gender;
   }

   public void setGender(String gender) {
      this.gender = gender;
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public List<String> getRoles() {
      return roles;
   }

   public void setRoles(List<String> roles) {
      this.roles = roles;
   }
}
DataDAO class is used toquery data in Database (Simulation).
DataDAO.java
package org.o7planning.securitywebapp.utils;

import java.util.HashMap;
import java.util.Map;

import org.o7planning.securitywebapp.bean.UserAccount;
import org.o7planning.securitywebapp.config.SecurityConfig;

public class DataDAO {

   private static final Map<String, UserAccount> mapUsers = new HashMap<String, UserAccount>();

   static {
      initUsers();
   }

   private static void initUsers() {

      // This user has a role as EMPLOYEE.
      UserAccount emp = new UserAccount("employee1", "123", UserAccount.GENDER_MALE, //
            SecurityConfig.ROLE_EMPLOYEE);

      // This user has 2 roles EMPLOYEE and MANAGER.
      UserAccount mng = new UserAccount("manager1", "123", UserAccount.GENDER_MALE, //
            SecurityConfig.ROLE_EMPLOYEE, SecurityConfig.ROLE_MANAGER);

      mapUsers.put(emp.getUserName(), emp);
      mapUsers.put(mng.getUserName(), mng);
   }

   // Find a User by userName and password.
   public static UserAccount findUser(String userName, String password) {
      UserAccount u = mapUsers.get(userName);
      if (u != null && u.getPassword().equals(password)) {
         return u;
      }
      return null;
   }

}

7. SecurityConfig & SecurityUtils

Lớp SecurityConfig giúp cấu hình các vai trò và các chức năng (các trang) được phép truy cập ứng với vai trò đó.
SecurityConfig.java
package org.o7planning.securitywebapp.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SecurityConfig {

	public static final String ROLE_MANAGER = "MANAGER";
	public static final String ROLE_EMPLOYEE = "EMPLOYEE";

	// String: Role
	// List<String>: urlPatterns.
	private static final Map<String, List<String>> mapConfig = new HashMap<String, List<String>>();

	static {
		init();
	}

	private static void init() {

		// Configure For "EMPLOYEE" Role.
		List<String> urlPatterns1 = new ArrayList<String>();

		urlPatterns1.add("/userInfo");
		urlPatterns1.add("/employeeTask");

		mapConfig.put(ROLE_EMPLOYEE, urlPatterns1);

		// Configure For "MANAGER" Role.
		List<String> urlPatterns2 = new ArrayList<String>();

		urlPatterns2.add("/userInfo");
		urlPatterns2.add("/managerTask");

		mapConfig.put(ROLE_MANAGER, urlPatterns2);
	}

	public static Set<String> getAllAppRoles() {
		return mapConfig.keySet();
	}

	public static List<String> getUrlPatternsForRole(String role) {
		return mapConfig.get(role);
	}

}
SecurityUtils class is a utility class, which has methods to help check if a request is required to be logged in or not, and whether such request is suitable for the role of user logged or not.
SecurityUtils.java
package org.o7planning.securitywebapp.utils;

import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.o7planning.securitywebapp.config.SecurityConfig;

public class SecurityUtils {

	// Check whether this 'request' is required to login or not.
	public static boolean isSecurityPage(HttpServletRequest request) {
		String urlPattern = UrlPatternUtils.getUrlPattern(request);

		Set<String> roles = SecurityConfig.getAllAppRoles();

		for (String role : roles) {
			List<String> urlPatterns = SecurityConfig.getUrlPatternsForRole(role);
			if (urlPatterns != null && urlPatterns.contains(urlPattern)) {
				return true;
			}
		}
		return false;
	}

	// Check if this 'request' has a 'valid role'?
	public static boolean hasPermission(HttpServletRequest request) {
		String urlPattern = UrlPatternUtils.getUrlPattern(request);

		Set<String> allRoles = SecurityConfig.getAllAppRoles();

		for (String role : allRoles) {
			if (!request.isUserInRole(role)) {
				continue;
			}
			List<String> urlPatterns = SecurityConfig.getUrlPatternsForRole(role);
			if (urlPatterns != null && urlPatterns.contains(urlPattern)) {
				return true;
			}
		}
		return false;
	}
}
UrlPatternUtils.java
package org.o7planning.securitywebapp.utils;

import java.util.Collection;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import javax.servlet.http.HttpServletRequest;

public class UrlPatternUtils {

   private static boolean hasUrlPattern(ServletContext servletContext, String urlPattern) {

      Map<String, ? extends ServletRegistration> map = servletContext.getServletRegistrations();

      for (String servletName : map.keySet()) {
         ServletRegistration sr = map.get(servletName);

         Collection<String> mappings = sr.getMappings();
         if (mappings.contains(urlPattern)) {
            return true;
         }

      }
      return false;
   }

   // servletPath:
   // ==> /spath
   // ==> /spath/*
   // ==> *.ext
   // ==> /
   public static String getUrlPattern(HttpServletRequest request) {
      ServletContext servletContext = request.getServletContext();
      String servletPath = request.getServletPath();
      String pathInfo = request.getPathInfo();

      String urlPattern = null;
      if (pathInfo != null) {
         urlPattern = servletPath + "/*";
         return urlPattern;
      }
      urlPattern = servletPath;

      boolean has = hasUrlPattern(servletContext, urlPattern);
      if (has) {
         return urlPattern;
      }
      int i = servletPath.lastIndexOf('.');
      if (i != -1) {
         String ext = servletPath.substring(i + 1);
         urlPattern = "*." + ext;
         has = hasUrlPattern(servletContext, urlPattern);

         if (has) {
            return urlPattern;
         }
      }
      return "/";
   }
}

8. SecurityFilter

SecurityFilter is a Servlet Filter, which does the duty of checking requests before allowing accessing the protected pages.

SecurityFilter reads "security configurations" declared in the SecurityConfig class.
SecurityFilter.java
package org.o7planning.securitywebapp.filter;

import java.io.IOException;
import java.util.List;

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.HttpServletResponse;

import org.o7planning.securitywebapp.bean.UserAccount;
import org.o7planning.securitywebapp.request.UserRoleRequestWrapper;
import org.o7planning.securitywebapp.utils.AppUtils;
import org.o7planning.securitywebapp.utils.SecurityUtils;

@WebFilter("/*")
public class SecurityFilter implements Filter {

	public SecurityFilter() {
	}

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;

		String servletPath = request.getServletPath();

		// User information stored in the Session.
		// (After successful login).
		UserAccount loginedUser = AppUtils.getLoginedUser(request.getSession());

		if (servletPath.equals("/login")) {
			chain.doFilter(request, response);
			return;
		}
		HttpServletRequest wrapRequest = request;

		if (loginedUser != null) {
			// User Name
			String userName = loginedUser.getUserName();

			// Roles
			List<String> roles = loginedUser.getRoles();

			// Wrap old request by a new Request with userName and Roles information.
			wrapRequest = new UserRoleRequestWrapper(userName, roles, request);
		}

		// Pages must be signed in.
		if (SecurityUtils.isSecurityPage(request)) {

			// If the user is not logged in,
			// Redirect to the login page.
			if (loginedUser == null) {

				String requestUri = request.getRequestURI();

				// Store the current page to redirect to after successful login.
				int redirectId = AppUtils.storeRedirectAfterLoginUrl(request.getSession(), requestUri);

				response.sendRedirect(wrapRequest.getContextPath() + "/login?redirectId=" + redirectId);
				return;
			}

			// Check if the user has a valid role?
			boolean hasPermission = SecurityUtils.hasPermission(wrapRequest);
			if (!hasPermission) {

				RequestDispatcher dispatcher //
						= request.getServletContext().getRequestDispatcher("/WEB-INF/views/accessDeniedView.jsp");

				dispatcher.forward(request, response);
				return;
			}
		}

		chain.doFilter(wrapRequest, response);
	}

	@Override
	public void init(FilterConfig fConfig) throws ServletException {

	}

}
UserRoleRequestWrapper.java
package org.o7planning.securitywebapp.request;

import java.security.Principal;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * An extension for the HTTPServletRequest that overrides the getUserPrincipal()
 * and isUserInRole(). We supply these implementations here, where they are not
 * normally populated unless we are going through the facility provided by the
 * container.
 * <p>
 * If he user or roles are null on this wrapper, the parent request is consulted
 * to try to fetch what ever the container has set for us. This is intended to
 * be created and used by the UserRoleFilter.
 * 
 * @author thein
 *
 */
public class UserRoleRequestWrapper extends HttpServletRequestWrapper {

	private String user;
	private List<String> roles = null;
	private HttpServletRequest realRequest;

	public UserRoleRequestWrapper(String user, List<String> roles, HttpServletRequest request) {
		super(request);
		this.user = user;
		this.roles = roles;
		this.realRequest = request;
	}

	@Override
	public boolean isUserInRole(String role) {
		if (roles == null) {
			return this.realRequest.isUserInRole(role);
		}
		return roles.contains(role);
	}

	@Override
	public Principal getUserPrincipal() {
		if (this.user == null) {
			return realRequest.getUserPrincipal();
		}

		// Make an anonymous implementation to just return our user
		return new Principal() {
			@Override
			public String getName() {
				return user;
			}
		};
	}
}

9. Home Page, Login, Logout

HomeServlet.java
package org.o7planning.securitywebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet({ "/", "/index" })
public class HomeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public HomeServlet() {
        super();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        RequestDispatcher dispatcher //
                = this.getServletContext().getRequestDispatcher("/WEB-INF/views/homeView.jsp");

        dispatcher.forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        doGet(request, response);
    }

}
LoginServlet.java
package org.o7planning.securitywebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.securitywebapp.bean.UserAccount;
import org.o7planning.securitywebapp.utils.AppUtils;
import org.o7planning.securitywebapp.utils.DataDAO;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public LoginServlet() {
		super();
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		RequestDispatcher dispatcher //
				= this.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");

		dispatcher.forward(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String userName = request.getParameter("userName");
		String password = request.getParameter("password");
		UserAccount userAccount = DataDAO.findUser(userName, password);

		if (userAccount == null) {
			String errorMessage = "Invalid userName or Password";

			request.setAttribute("errorMessage", errorMessage);

			RequestDispatcher dispatcher //
					= this.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");

			dispatcher.forward(request, response);
			return;
		}

		AppUtils.storeLoginedUser(request.getSession(), userAccount);

		// 
		int redirectId = -1;
		try {
			redirectId = Integer.parseInt(request.getParameter("redirectId"));
		} catch (Exception e) {
		}
		String requestUri = AppUtils.getRedirectAfterLoginUrl(request.getSession(), redirectId);
		if (requestUri != null) {
			response.sendRedirect(requestUri);
		} else {
			// Default after successful login
			// redirect to /userInfo page
			response.sendRedirect(request.getContextPath() + "/userInfo");
		}

	}

}
AppUtils.java
package org.o7planning.securitywebapp.utils;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.o7planning.securitywebapp.bean.UserAccount;

public class AppUtils {

	private static int REDIRECT_ID = 0;

	private static final Map<Integer, String> id_uri_map = new HashMap<Integer, String>();
	private static final Map<String, Integer> uri_id_map = new HashMap<String, Integer>();

	// Store user info in Session.
	public static void storeLoginedUser(HttpSession session, UserAccount loginedUser) {
		// On the JSP can access via ${loginedUser}
		session.setAttribute("loginedUser", loginedUser);
	}

	// Get the user information stored in the session.
	public static UserAccount getLoginedUser(HttpSession session) {
		UserAccount loginedUser = (UserAccount) session.getAttribute("loginedUser");
		return loginedUser;
	}

	public static int storeRedirectAfterLoginUrl(HttpSession session, String requestUri) {
		Integer id = uri_id_map.get(requestUri);

		if (id == null) {
			id = REDIRECT_ID++;

			uri_id_map.put(requestUri, id);
			id_uri_map.put(id, requestUri);
			return id;
		}

		return id;
	}

	public static String getRedirectAfterLoginUrl(HttpSession session, int redirectId) {
		String url = id_uri_map.get(redirectId);
		if (url != null) {
			return url;
		}
		return null;
	}

}
LogoutServlet.java
package org.o7planning.securitywebapp.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public LogoutServlet() {
		super();
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.getSession().invalidate();

		// Redrect to Home Page.
		response.sendRedirect(request.getContextPath() + "/");

	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doGet(request, response);
	}

}
UserInfoServlet.java
package org.o7planning.securitywebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/userInfo")
public class UserInfoServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;

   public UserInfoServlet() {
      super();
   }

   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

      RequestDispatcher dispatcher //
            = this.getServletContext().getRequestDispatcher("/WEB-INF/views/userInfoView.jsp");

      dispatcher.forward(request, response);
   }

   @Override
   protected void doPost(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {
      
      doGet(request, response);
   }

}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://java.sun.com/xml/ns/javaee"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      id="WebApp_ID" version="3.0">
      
  <display-name>SecurityWebApp</display-name>
 
 
  <welcome-file-list>
 
    <welcome-file>/</welcome-file>
     
  </welcome-file-list>
 
 
</web-app>
/WEB-INF/views/_menu.jsp
<a href="${pageContext.request.contextPath}/employeeTask">
  Employee Task
</a>
||
<a href="${pageContext.request.contextPath}/managerTask">
  Manager Task
</a>
||
<a href="${pageContext.request.contextPath}/userInfo">
  User Info
</a>       
||
<a href="${pageContext.request.contextPath}/login">
  Login
</a>
||
<a href="${pageContext.request.contextPath}/logout">
  Logout
</a>

&nbsp;
<span style="color:red">[ ${loginedUser.userName} ]</span>
/WEB-INF/views/homeView.jsp
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Home Page</title>
   </head>
   <body>
   
      <jsp:include page="_menu.jsp"></jsp:include>
   
      <h3>Home Page</h3>
            
   </body>
</html>
/WEB-INF/views/loginView.jsp
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Login</title>
   </head>
   <body>

      <jsp:include page="_menu.jsp"></jsp:include>   

      <h3>Login Page</h3>

      <p style="color: red;">${errorString}</p>

      <form method="POST" action="${pageContext.request.contextPath}/login">
         <input type="hidden" name="redirectId" value="${param.redirectId}" />
         <table border="0">
            <tr>
               <td>User Name</td>
               <td><input type="text" name="userName" value= "${user.userName}" /> </td>
            </tr>
            <tr>
               <td>Password</td>
               <td><input type="password" name="password" value= "${user.password}" /> </td>
            </tr>
         
            <tr>
               <td colspan ="2">
                  <input type="submit" value= "Submit" />
                  <a href="${pageContext.request.contextPath}/">Cancel</a>
               </td>
            </tr>
         </table>
      </form>

      <p style="color:blue;">Login with:</p>
      
      employee1/123 <br>
      manager1/123
     
 

   </body>
</html>
/WEB-INF/views/userInfoView.jsp
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>User Info</title>
   </head>
   <body>

     <jsp:include page="_menu.jsp"></jsp:include>

      <h3>Hello: ${loginedUser.userName}</h3>

      User Name: <b>${loginedUser.userName}</b>
      <br />
      Gender: ${loginedUser.gender } <br />


   </body>
</html>
Run Application:

10. Pages must be logged in

EmployeeTaskServlet.java
package org.o7planning.securitywebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/employeeTask")
public class EmployeeTaskServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;

   public EmployeeTaskServlet() {
      super();
   }

   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

      RequestDispatcher dispatcher //
            = this.getServletContext()//
                  .getRequestDispatcher("/WEB-INF/views/employeeTaskView.jsp");

      dispatcher.forward(request, response);
   }

   @Override
   protected void doPost(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

      doGet(request, response);
   }

}
ManagerTaskServlet.java
package org.o7planning.securitywebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/managerTask")
public class ManagerTaskServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;

   public ManagerTaskServlet() {
      super();
   }

   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

      RequestDispatcher dispatcher //
            = this.getServletContext()//
                  .getRequestDispatcher("/WEB-INF/views/managerTaskView.jsp");

      dispatcher.forward(request, response);
   }

   @Override
   protected void doPost(HttpServletRequest request, HttpServletResponse response)
         throws ServletException, IOException {

      doGet(request, response);
   }

}
/WEB-INF/views/employeeTaskView.jsp
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Employee Task</title>
   </head>
   <body>
  
      <jsp:include page="_menu.jsp"></jsp:include>
      
      <h3>Employee Task</h3>
      
      Hello, This is a protected page!
      
   </body>
</html>
/WEB-INF/views/managerTaskView.jsp
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Manager Task</title>
   </head>
   
   <body>
   
      <jsp:include page="_menu.jsp"></jsp:include>
      
      <h3>Manager Task</h3>
      
      Hello, This is a protected page!
      
   </body>
</html>
/WEB-INF/views/accessDenied.jsp
<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>Access Denied</title>
   </head>
   <body>
   
      <jsp:include page="_menu.jsp"></jsp:include>
   
      <br/><br/>
      
      <h3 style="color:red;">Access Denied!</h3>
            
   </body>
</html>
Run Application:
Run the application and log in with userName = "employee1", whichis user with the role of "EMPLOYEE".
Run the application and log in with userName = "manager1", which is user with the 2 roles such as "EMPLOYEE" and "MANAGER".