devstory

Créez une application de connexion simple et sécurisez les pages avec Java Servlet Filter

  1. Pourquoi la sécurité est-elle utilisée?
  2. Le concepte de Role et Principal
  3. La sécurité avec Servlet Filter
  4. L'objectif de l'exemple
  5. Créer l'application
  6. UserAccount & DataDAO
  7. SecurityConfig & SecurityUtils
  8. SecurityFilter
  9. Home Page, Login, Logout
  10. Des pages doivent être connectées

1. Pourquoi la sécurité est-elle utilisée?

La sécurité (Security) est un aspect important d'une application avec le transfert de données importantes sur Internet.
Authentication (L'authentification)
L'authentification est le processus par lequel les privilèges d'accès (access privileges) des utilisateurs sont vérifiés avant leur entrée dans la zone protégée d'un Website. Il existe deux approches d'authentification principales: l'authentification de base et l'authentification basée sur un formulaire (Form-based authentication).
Basic Authentication (L'authentification de base)
Pour l'authentification de base, un utilisateur peut normalement accéder à toutes les pages (page) complètement. Pour les pages qui exigent la sécurité, une fenêtre s'affichera pour que l'utilisateur saisit son username/password. Les informations de username/password seront regroupées pour être envoyées avec la demande (request) au Server.
Lorsque l'utilisateur saisit un chemin sur le navigateur et appuyez sur Enter pour demander l'accès une page (page). Une information "User Agent" sera créée et envoyée avec la demande. Normalement, cette information comprend les informations du navigateur de l'utilisateur, les informations du système d'exploitation. En cas d'authentification de base, les informations de username/password sont regroupées dans "User Agent".
Dans ce poste, je ne mentionne pas de l'authentification à base en détails.
Form-based Authentication (L'authentification basée sur un formulaire)
La plupart des sites Web utilisent l'authentification basée sur un formulaire (Form-based Authentication). Un site web permet à l'utilisateur d'accéder à chaque page commune sans demander le mot de passe. Cependant, si l'utilisateur accède une page protégée, il redirigera vers une page de connexion.
Dans cette leçon, je détaillerai l'utilisation d'un Servlet Filter pour garder une application Java Web secrète.

2. Le concepte de Role et Principal

En sécurité, il y a 2 concepts importants qui sont Principal et Role.
Role
Role (Le rôle) est un ensemble d'autorisations (permission) d'une application.
Pour plus de simplicité, je donne un exemple, l'application ABC joue 2 rôles "EMPLOYEE" (employé) et "MANAGER" (le gestionnaire).
  • Le rôle "EMPLOYEE" est autorisé à utiliser les fonctions de vente et la fonction de création des informations du client..
  • Le rôle "MANAGER" est autorisé à utiliser les fonctions de gestion des employés et à voir les rapports sur les revenus.
Principal
Principal peut être temporairement compris comme un "Sujet" après s'être connecté à un système. Il a le droit de faire quelque chose dans le système. Un "Sujet" peut jouer un ou plusieurs rôles. Cela dépend des autorisations d'application pour chaque compte d'utilisateur différent.

3. La sécurité avec Servlet Filter

Dans l'application Java Servlet, un Servlet Filter est particulièremeny utilisé pour gérer la sécurité. Il est généralement appelé comme Security Filter.
Voici les principes de fonctionnement du Security Filter.
Lorsque l'utilisateur accède à une page (page) protégée, le Security Filter le testera. Si l'utilisateur n'est pas connecté, la demande de l'utilisateur sera redirigée (redirect) vers la page de connexion.
Si l'utilisateur a accédé avec succès, un objet Principal est créé. Il apporte les informations de l'utilisateur, y compris les rôles.
Si l'utilisateur s'est connecté avec succès auparavant et a accédé à une page (page) protégée. Le Security Filter vérifiera si les rôles de l'utilisateur sont appropriés pour accéder à cette page ou non. Si elle n'est pas valide, elle affichera à l'utilisateur une page informant que l'accès est refusé (Access Denied).

4. L'objectif de l'exemple

Ceci est la structure de l'application que nous effectuerons :
L'application comprend 2 rôles (Role) qui sont EMPLOYEE et MANAGER.
  1. Le rôle EMPLOYEE permet à accéder aux 2 pages /userInfo et /employeeTask
  2. Le rôle MANAGER permet à accéder aux 2 pages /userInfo et /managerTask.
Toutes les autres pages de l'application ne demandent pas de connexion.
Il y a 2 utilisateurs (user) qui sont employee1 et manager1.
  • L'utilisateur employee1 est attribué le rôle de EMPLOYEE
  • L'utilisateur manager1 est attribué les rôles de MANAGER et EMPLOYEE.
L'utilisateur peut normalement accéder à toutes les pages non protégées. Cependant, si l'utilisateur visite une page ABC protégée, il redirigera (redirect) vers la page de connexion. SI l'utilisateur se connecte avec succès, il y aura 2 situations qui se poduiront :
  • L'application redirigera à la page ABC après l'achèvement de connexion, si userName joue le rôle approprié.
  • L'application affichera que l'accès est refusé (Access Denied) si userName joue le rôle approprié.

5. Créer l'application

Sur Eclipse créez un "Dynamic Web Project" baptisé SecurityWebApp, et configurez pourqu'il puisse exécuter sur Tomcat Server. Je ne mentionne plus en détails les étapes pour le faire, vous pouvez consulter dans le lien de la lecon ci-dessous :

6. UserAccount & DataDAO

La classe UserAccount représente d'utilisateur de l'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;
   }
}
La classe DataDAO sert à requêter des données dans la base de données (La 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

La classe SecurityConfig sert à configurer des rôles et des fonctionnements des pages (page) qui sont l'autorité d'accéder à ce rôle.
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() {

		// Configurez pour le rôle "EMPLOYEE".
		List<String> urlPatterns1 = new ArrayList<String>();

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

		mapConfig.put(ROLE_EMPLOYEE, urlPatterns1);

		// Configurez pour le rôle "MANAGER".
		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);
	}

}
La classe SecurityUtils est une classe utilitaire. Elle ont des méthodes qui aident à vérifier si une request (demande) est requise de connexion ou non et si cette ladite request est appropriée au rôle de l'utilisateur qui s'est connecté ou non.
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 {

	// Vérifiez si cette 'request' est requise de se connecter ou non.
	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;
	}

	// Vérifiez si cette 'request' dont le rôle est validé ou non?
	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 est un Servlet Filter, qui sert à vérifier les request avant d'autoriser l'accès aux pages (page) protégées.

SecurityFilter lit "configurations de sécurité" déclarées dans la classe SecurityConfig.
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();

		// L'informstion d'utilisateur est stockée dans Session
		// (Après l'achèvement de connexion).
		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();

			// Des rôles (Role).
			List<String> roles = loginedUser.getRoles();

			// Envelopper l'ancienne demande (request) par une nouvelle demande avec les informations userName et Roles.
			wrapRequest = new UserRoleRequestWrapper(userName, roles, request);
		}

		// Les pages doivent être connectées.
		if (SecurityUtils.isSecurityPage(request)) {

			// Si l'utilisateur n'est pas connecté,
			// Redirect (redirigez) vers la page de connexion
			if (loginedUser == null) {

				String requestUri = request.getRequestURI();

				// Stockez la page en cours à rediriger après l'achèvement de la connexion.
				int redirectId = AppUtils.storeRedirectAfterLoginUrl(request.getSession(), requestUri);

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

			// Vérifiez si l'utilisateur a un rôle valide?
			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 {
			// Par défaut, après l'achèvement de la connexion
			// redirigez à la page /userInfo
			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>();

	// Stockez l'information d'utilisateur dans Session.
	public static void storeLoginedUser(HttpSession session, UserAccount loginedUser) {
		// Sur JSP il est possible d'accéder via ${loginedUser}
		session.setAttribute("loginedUser", loginedUser);
	}

	// Obtenez de l'information d'utilisateur stockée dans 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>
Exécutez l'exemple:

10. Des pages doivent être connectées

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>
Exéctez l'exemple:
Exécutez l'application et connectez- vous avec userName = "employee1", qui est l'utilisateur jouant le rôle de "EMPLOYEE".
Exécutez l'application et connectez- vous avec userName = "manager1", qui est l'utilisateur jouant 2 rôles tels que "EMPLOYEE" et "MANAGER".