Gestion de session en Java Les applications Web Servlet sont un sujet très intéressant. La session en Java Servlet est gérée de différentes manières, telles que les cookies, l’API HttpSession, le réécriture d’URL, etc. Cet article est le troisième de la série de tutoriels sur les applications Web en Java. Vous voudrez peut-être consulter les deux articles précédents également.
Gestion de session en Java
Cet article vise à expliquer la gestion de session dans les servlets en utilisant différentes techniques et des programmes exemples.
-
Qu’est-ce qu’une session ?
Le protocole HTTP et les serveurs Web sont sans état, ce qui signifie que pour le serveur Web, chaque requête est une nouvelle requête à traiter et il ne peut pas identifier si elle provient d’un client qui a déjà envoyé une requête auparavant. Mais parfois, dans les applications Web, nous devons savoir qui est le client et traiter la requête en conséquence. Par exemple, une application de panier d’achat doit savoir qui envoie la demande d’ajout d’un article et dans quel panier l’article doit être ajouté, ou qui envoie la demande de paiement afin de pouvoir facturer le montant au bon client. Une session est un état de conversation entre le client et le serveur et elle peut consister en plusieurs requêtes et réponses entre le client et le serveur. Étant donné que HTTP et le serveur Web sont tous deux sans état, le seul moyen de maintenir une session est de transmettre des informations uniques sur la session (identifiant de session) entre le serveur et le client dans chaque requête et réponse. Il existe plusieurs façons de fournir un identifiant unique dans la requête et la réponse.
-
Authentification de l’utilisateur – C’est la méthode très courante où l’utilisateur peut fournir des informations d’authentification à partir de la page de connexion, puis nous pouvons transmettre les informations d’authentification entre le serveur et le client pour maintenir la session. Cette méthode n’est pas très efficace car elle ne fonctionnera pas si le même utilisateur est connecté à partir de différents navigateurs.
-
Champ caché HTML – Nous pouvons créer un champ caché unique dans le HTML et lorsque l’utilisateur commence à naviguer, nous pouvons définir sa valeur unique pour l’utilisateur et suivre la session. Cette méthode ne peut pas être utilisée avec des liens car elle nécessite que le formulaire soit soumis à chaque fois qu’une requête est effectuée du client vers le serveur avec le champ caché. De plus, ce n’est pas sécurisé car nous pouvons obtenir la valeur du champ caché à partir de la source HTML et l’utiliser pour pirater la session.
-
Réécriture d’URL – Nous pouvons ajouter un paramètre d’identifiant de session à chaque requête et réponse pour suivre la session. Cela est très fastidieux car nous devons suivre ce paramètre dans chaque réponse et nous assurer qu’il ne entre pas en conflit avec d’autres paramètres.
-
Cookies – Les cookies sont de petites informations envoyées par le serveur Web dans l’en-tête de réponse et qui sont stockées dans les cookies du navigateur. Lorsque le client fait une autre demande, il ajoute le cookie à l’en-tête de la requête et nous pouvons l’utiliser pour suivre la session. Nous pouvons maintenir une session avec des cookies mais si le client désactive les cookies, cela ne fonctionnera pas.
-
API de gestion de session – L’API de gestion de session est construite sur les méthodes ci-dessus pour le suivi de session. Certains des principaux inconvénients de toutes les méthodes ci-dessus sont :
- La plupart du temps, nous ne voulons pas seulement suivre la session, nous devons stocker certaines données dans la session que nous pouvons utiliser dans les futures requêtes. Cela nécessitera beaucoup d’efforts si nous essayons de mettre en œuvre cela.
- Toutes les méthodes ci-dessus ne sont pas complètes en elles-mêmes, aucune d’entre elles ne fonctionnera dans un scénario particulier. Nous avons donc besoin d’une solution qui puisse utiliser ces méthodes de suivi de session pour fournir une gestion de session dans tous les cas.
C’est pourquoi nous avons besoin de l’API de gestion de session et la technologie de servlet J2EE est livrée avec une API de gestion de session que nous pouvons utiliser.
-
-
Gestion de session en Java – Cookies
Les cookies sont largement utilisés dans les applications Web pour personnaliser les réponses en fonction de vos choix ou pour suivre une session. Avant de passer à l’API de gestion de session Servlet, je voudrais montrer comment nous pouvons suivre une session avec des cookies à travers une petite application Web. Nous allons créer une application Web dynamique ServletCookieExample avec une structure de projet comme indiqué dans l’image ci-dessous.
Le descripteur de déploiement web.xml de l’application Web est :
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>ServletCookieExample</display-name> <welcome-file-list> <welcome-file>login.html</welcome-file> </welcome-file-list> </web-app>
La page d’accueil de notre application est login.html où nous récupérerons les détails d’authentification de l’utilisateur.
<!DOCTYPE html> <html> <head> <meta charset="US-ASCII"> <title>Page de connexion</title> </head> <body> <form action="LoginServlet" method="post"> Nom d'utilisateur : <input type="text" name="user"> <br> Mot de passe : <input type="password" name="pwd"> <br> <input type="submit" value="Connexion"> </form> </body> </html>
Voici le LoginServlet qui gère la demande de connexion.
package com.journaldev.servlet.session; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Implémentation du servlet LoginServlet */ @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; private final String userID = "Pankaj"; private final String password = "journaldev"; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // obtenir les paramètres de demande pour l'identifiant utilisateur et le mot de passe String user = request.getParameter("user"); String pwd = request.getParameter("pwd"); if(userID.equals(user) && password.equals(pwd)){ Cookie loginCookie = new Cookie("user",user); // définir le cookie expirant dans 30 minutes loginCookie.setMaxAge(30*60); response.addCookie(loginCookie); response.sendRedirect("LoginSuccess.jsp"); }else{ RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html"); PrintWriter out= response.getWriter(); out.println("<font color=red>Soit le nom d'utilisateur soit le mot de passe est incorrect.</font>"); rd.include(request, response); } } }
Remarquez le cookie que nous définissons dans la réponse et ensuite le transmettons à LoginSuccess.jsp, ce cookie sera utilisé là pour suivre la session. Remarquez également que le délai d’expiration du cookie est fixé à 30 minutes. Idéalement, il devrait y avoir une logique complexe pour définir la valeur du cookie pour le suivi de session afin qu’elle ne entre pas en collision avec une autre demande.
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Page de succès de la connexion</title> </head> <body> <% String userName = null; Cookie[] cookies = request.getCookies(); if(cookies !=null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("user")) userName = cookie.getValue(); } } if(userName == null) response.sendRedirect("login.html"); %> <h3>Salut <%=userName %>, Connexion réussie.</h3> <br> <form action="LogoutServlet" method="post"> <input type="submit" value="Déconnexion" > </form> </body> </html>
Remarquez que si nous essayons d’accéder directement au JSP, il nous redirigera vers la page de connexion. Lorsque nous cliquerons sur le bouton Déconnexion, nous devrions nous assurer que le cookie est supprimé du navigateur client.
package com.journaldev.servlet.session;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/**
* Implémentation du servlet LogoutServlet
*/
@WebServlet("/LogoutServlet")
public class LogoutServlet extends HttpServlet {
private static final long serialVersionUID = 1L;protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
Cookie loginCookie = null;
Cookie[] cookies = request.getCookies();
if(cookies != null){
for(Cookie cookie : cookies){
if(cookie.getName().equals("user")){
loginCookie = cookie;
break;
}
}
}
if(loginCookie != null){
loginCookie.setMaxAge(0);
response.addCookie(loginCookie);
}
response.sendRedirect - java
Séance en Java Servlet – HttpSession
L’API Servlet fournit la gestion des sessions via l’interface
HttpSession
. Nous pouvons obtenir la session à partir de l’objet HttpServletRequest en utilisant les méthodes suivantes. HttpSession nous permet de définir des objets en tant qu’attributs qui peuvent être récupérés dans des requêtes futures.- HttpSession getSession() – Cette méthode retourne toujours un objet HttpSession. Elle renvoie l’objet de session attaché à la requête, si la requête n’a pas de session attachée, alors elle crée une nouvelle session et la renvoie.
- HttpSession getSession(boolean flag) – Cette méthode retourne l’objet HttpSession si la requête a une session, sinon elle renvoie null.
Certaines des méthodes importantes de HttpSession sont :
- String getId() – Retourne une chaîne contenant l’identifiant unique attribué à cette session.
- Object getAttribute(String name) – Retourne l’objet lié au nom spécifié dans cette session, ou null s’il n’y a aucun objet lié sous ce nom. Quelques autres méthodes pour travailler avec les attributs de session sont
getAttributeNames()
,removeAttribute(String name)
etsetAttribute(String name, Object value)
. - long getCreationTime() – Retourne l’heure à laquelle cette session a été créée, mesurée en millisecondes depuis minuit le 1er janvier 1970 GMT. Nous pouvons obtenir l’heure de la dernière utilisation avec la méthode
getLastAccessedTime()
. - setMaxInactiveInterval(int interval) – Spécifie le temps, en secondes, entre les requêtes du client avant que le conteneur de servlet n’invalide cette session. Nous pouvons obtenir la valeur du délai d’expiration de session à partir de la méthode
getMaxInactiveInterval()
. - ServletContext getServletContext() – Retourne l’objet ServletContext pour l’application.
- boolean isNew() – Renvoie true si le client ne connaît pas encore la session ou s’il choisit de ne pas rejoindre la session.
- void invalidate() – Invalide cette session puis délie tout objet qui lui est lié.
Compréhension du Cookie JSESSIONID
Lorsque nous utilisons la méthode HttpServletRequest getSession() et qu’elle crée une nouvelle requête, elle crée le nouvel objet HttpSession et ajoute également un cookie à l’objet de réponse avec le nom JSESSIONID et la valeur comme identifiant de session. Ce cookie est utilisé pour identifier l’objet HttpSession dans les futures requêtes du client. Si les cookies sont désactivés côté client et que nous utilisons la réécriture d’URL, alors cette méthode utilise la valeur jsessionid de l’URL de la requête pour trouver la session correspondante. Le cookie JSESSIONID est utilisé pour le suivi de session, nous ne devrions donc pas l’utiliser à des fins d’application pour éviter tout problème lié à la session. Voyons un exemple de gestion de session en utilisant l’objet HttpSession. Nous allons créer un projet web dynamique dans Eclipse avec le contexte de servlet comme ServletHttpSessionExample. La structure du projet ressemblera à l’image ci-dessous.
login.html est le même que dans l’exemple précédent et est défini comme page d’accueil de l’application dans web.xml Le servlet LoginServlet créera la session et définira les attributs que nous pouvons utiliser dans d’autres ressources ou dans des requêtes futures.
package com.journaldev.servlet.session; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Implémentation de servlet de la classe LoginServlet */ @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; private final String userID = "admin"; private final String password = "password"; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // obtenir les paramètres de la requête pour l'identifiant utilisateur et le mot de passe String user = request.getParameter("user"); String pwd = request.getParameter("pwd"); if(userID.equals(user) && password.equals(pwd)){ HttpSession session = request.getSession(); session.setAttribute("user", "Pankaj"); // définir la session pour expirer en 30 minutes session.setMaxInactiveInterval(30*60); Cookie userName = new Cookie("user", user); userName.setMaxAge(30*60); response.addCookie(userName); response.sendRedirect("LoginSuccess.jsp"); }else{ RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html"); PrintWriter out= response.getWriter(); out.println("<font color=red>Soit le nom d'utilisateur soit le mot de passe est incorrect.</font>"); rd.include(request, response); } } }
Notre code LoginSuccess.jsp est donné ci-dessous.
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Page de succès de connexion</title -
Gestion de session en Java Servlet – Réécriture d’URL
Comme nous l’avons vu dans la dernière section, nous pouvons gérer une session avec HttpSession, mais si nous désactivons les cookies dans le navigateur, cela ne fonctionnera pas car le serveur ne recevra pas le cookie JSESSIONID du client. L’API Servlet fournit une prise en charge de la réécriture d’URL que nous pouvons utiliser pour gérer la session dans ce cas. Le meilleur, c’est qu’au point de vue du codage, c’est très facile à utiliser et cela ne nécessite qu’une étape – l’encodage de l’URL. Une autre bonne chose avec l’encodage d’URL Servlet est que c’est une approche de secours et elle entre en jeu uniquement si les cookies du navigateur sont désactivés. Nous pouvons encoder l’URL avec la méthode
encodeURL()
de HttpServletResponse et si nous devons rediriger la demande vers une autre ressource et que nous voulons fournir des informations de session, nous pouvons utiliser la méthodeencodeRedirectURL()
. Nous allons créer un projet similaire à celui ci-dessus, sauf que nous utiliserons des méthodes de réécriture d’URL pour nous assurer que la gestion de session fonctionne correctement même si les cookies sont désactivés dans le navigateur. La structure du projet ServletSessionURLRewriting dans eclipse ressemble à l’image ci-dessous.package com.journaldev.servlet.session; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Implémentation du Servlet de connexion */ @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; private final String userID = "admin"; private final String password = "password"; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // obtenir les paramètres de la demande pour l'identifiant utilisateur et le mot de passe String user = request.getParameter("user"); String pwd = request.getParameter("pwd"); if(userID.equals(user) && password.equals(pwd)){ HttpSession session = request.getSession(); session.setAttribute("user", "Pankaj"); // définir la session expirée dans 30 minutes session.setMaxInactiveInterval(30*60); Cookie userName = new Cookie("user", user); response.addCookie(userName); //Obtenir la chaîne d'URL codée String encodedURL = response.encodeRedirectURL("LoginSuccess.jsp"); response.sendRedirect(encodedURL); }else{ RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html"); PrintWriter out= response.getWriter(); out.println("<font color=red>Soit le nom d'utilisateur, soit le mot de passe est incorrect.</font>"); rd.include(request, response); } } }
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Page de succès de connexion</title> </head> <body> <% //autoriser l'accès uniquement si la session existe String user = null; if(session.getAttribute("user") == null){ response.sendRedirect("login.html"); }else user = (String) session.getAttribute("user"); String userName = null; String sessionID = null; Cookie[] cookies = request.getCookies(); if(cookies !=null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("user")) userName = cookie.getValue(); if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue(); } }else{ sessionID = session.getId(); } %> <h3>Salut <%=userName %>, connexion réussie. Votre ID de session=<%=sessionID %></h3> <br> Utilisateur=<%=user %> <br> <!-- besoin d'encoder toutes les URL où nous voulons que les informations de session soient transmises --> <a href="<%=response.encodeURL("CheckoutPage.jsp") %>">Page de paiement</a> <form action="<%=response.encodeURL("LogoutServlet") %>" method="post"> <input type="submit" value="Déconnexion" > </form> </body> </html>
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Page de succès de connexion</title> </head> <body> <% String userName = null; //autoriser l'accès uniquement si la session existe if(session.getAttribute("user") == null){ response.sendRedirect("login.html"); }else userName = (String) session.getAttribute("user"); String sessionID = null; Cookie[] cookies = request.getCookies(); if(cookies !=null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("user")) userName = cookie.getValue(); } } %> <h3>Salut <%=userName %>, effectuez le paiement.</h3> <br> <form action="<%=response.encodeURL("LogoutServlet") %>" method="post"> <input type="submit" value="Déconnexion" > </form> </body> </html>
package com.journaldev.servlet.session;
import java.io.IOException;
import javax.servlet.ServletException;
import
C’est tout pour la gestion de session dans les servlets Java, nous examinerons les filtres de servlets et les écouteurs et les cookies dans les articles à venir. Mise à jour : Consultez l’article suivant de la série Filtre Servlet.