Gestione sessione in Java – HttpServlet, Cookies, URL Rewriting

Gestione delle sessioni in Java Le applicazioni web Servlet sono un argomento molto interessante. Le sessioni in Java Servlet vengono gestite attraverso diversi modi, come i Cookie, l’API HttpSession, il rewriting degli URL, ecc. Questo è il terzo articolo della serie di tutorial sulle applicazioni web in Java, potresti voler dare un’occhiata anche ai due articoli precedenti.

  1. Tutorial sulle applicazioni web Java
  2. Tutorial sui Servlet Java

Gestione delle sessioni in Java

Questo articolo si propone di spiegare la gestione delle sessioni nei servlet utilizzando diverse tecniche e con esempi di programmi.

  1. Cosa è una sessione?

  2. Gestione delle sessioni in Java – Cookie

  3. Sessione in Java Servlet – HttpSession

  4. Gestione della sessione in Java Servlet – Riscrittura URL

  5. Cosa è una sessione?

    Il protocollo HTTP e i server Web sono senza stato, il che significa che per il server Web ogni richiesta è una nuova richiesta da elaborare e non possono identificare se proviene da un client che ha inviato richieste in precedenza. Ma a volte nelle applicazioni web, dovremmo sapere chi è il client e elaborare la richiesta di conseguenza. Ad esempio, un’applicazione di carrello della spesa dovrebbe sapere chi sta inviando la richiesta per aggiungere un articolo e in quale carrello l’articolo deve essere aggiunto o chi sta inviando la richiesta di checkout in modo che possa addebitare l’importo al cliente corretto. La sessione è uno stato conversazionale tra client e server e può consistere in molteplici richieste e risposte tra client e server. Poiché HTTP e il server Web sono entrambi senza stato, l’unico modo per mantenere una sessione è quando vengono passate informazioni univoche sulla sessione (ID sessione) tra server e client in ogni richiesta e risposta. Ci sono diversi modi per fornire un identificatore univoco in richiesta e risposta.

    1. Autenticazione utente – Questo è il modo più comune in cui l’utente può fornire credenziali di autenticazione dalla pagina di login e quindi possiamo passare le informazioni di autenticazione tra server e client per mantenere la sessione. Questo metodo non è molto efficace perché non funzionerà se lo stesso utente accede da browser diversi.

    2. Campo nascosto HTML – Possiamo creare un campo nascosto unico nell’HTML e quando l’utente inizia a navigare, possiamo impostare il suo valore unico per l’utente e tenere traccia della sessione. Questo metodo non può essere utilizzato con i collegamenti perché è necessario inviare il modulo ogni volta che viene effettuata una richiesta dal client al server con il campo nascosto. Inoltre, non è sicuro perché possiamo ottenere il valore del campo nascosto dalla sorgente HTML e usarlo per hackerare la sessione.

    3. Riscrittura URL – Possiamo aggiungere un parametro identificatore di sessione con ogni richiesta e risposta per tenere traccia della sessione. Questo è molto tedioso perché dobbiamo tenere traccia di questo parametro in ogni risposta e assicurarci che non entri in conflitto con altri parametri.

    4. Cookies – I cookie sono piccole informazioni inviate dal server Web nell’intestazione della risposta e vengono memorizzati nei cookie del browser. Quando il client effettua ulteriori richieste, aggiunge il cookie all’intestazione della richiesta e possiamo utilizzarlo per tenere traccia della sessione. Possiamo mantenere una sessione con i cookie, ma se il client disabilita i cookie, allora non funzionerà.

    5. API di gestione sessione – L’API di gestione sessione è costruita sopra i metodi sopra citati per il tracciamento delle sessioni. Alcuni dei principali svantaggi di tutti i metodi sopra citati sono:

      • Nella maggior parte dei casi non vogliamo solo tracciare la sessione, dobbiamo memorizzare alcuni dati nella sessione che possiamo utilizzare in future richieste. Questo richiederà molto sforzo se cerchiamo di implementarlo.
      • Tutti i metodi sopra descritti non sono completi di per sé, tutti loro non funzioneranno in uno scenario particolare. Quindi abbiamo bisogno di una soluzione che possa utilizzare questi metodi di tracciamento della sessione per fornire la gestione della sessione in tutti i casi.

      Ecco perché abbiamo bisogno di API di gestione sessione e la tecnologia Servlet J2EE viene fornita con API di gestione sessione che possiamo utilizzare.

  6. Gestione della sessione in Java – Cookie

    I cookie sono ampiamente utilizzati nelle applicazioni web per personalizzare la risposta in base alla tua scelta o per tenere traccia della sessione. Prima di procedere con l’API di gestione della sessione Servlet, vorrei mostrare come possiamo tenere traccia della sessione con i cookie attraverso una piccola applicazione web. Creeremo un’applicazione web dinamica ServletCookieExample con una struttura del progetto come nell’immagine seguente. Il descrittore di distribuzione web.xml dell’applicazione web è:

    <?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 pagina di benvenuto della nostra applicazione è login.html, dove otterremo i dettagli di autenticazione dall’utente.

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="US-ASCII">
    <title>Pagina di accesso</title>
    </head>
    <body>
    
    <form action="LoginServlet" method="post">
    
    Nome utente: <input type="text" name="user">
    <br>
    Password: <input type="password" name="pwd">
    <br>
    <input type="submit" value="Accedi">
    </form>
    </body>
    </html>
    

    Ecco il LoginServlet che si occupa della richiesta di accesso.

    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;
    
    /**
     * Implementazione del servlet della classe 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 {
    
    		// ottieni i parametri della richiesta per userID e password
    		String user = request.getParameter("user");
    		String pwd = request.getParameter("pwd");
    		
    		if(userID.equals(user) && password.equals(pwd)){
    			Cookie loginCookie = new Cookie("user",user);
    			// impostazione del cookie per scadere in 30 minutiuti
    			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>Sia il nome utente che la password sono errati.</font>");
    			rd.include(request, response);
    		}
    
    	}
    
    }
    

    Nota il cookie che stiamo impostando sulla risposta e poi lo inoltriamo a LoginSuccess.jsp, questo cookie verrà utilizzato lì per tracciare la sessione. Notare anche che il timeout del cookie è impostato su 30 minuti. Idealmente dovrebbe esserci una logica complessa per impostare il valore del cookie per il tracciamento della sessione in modo che non entri in collisione con nessun’altra richiesta.

    <%@ 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>Pagina di accesso riuscita</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>Ciao <%=userName %>, Accesso riuscito.</h3>
    <br>
    <form action="LogoutServlet" method="post">
    <input type="submit" value="Esci" >
    </form>
    </body>
    </html>
    

    Nota che se proviamo ad accedere direttamente alla JSP, verrà inoltrato alla pagina di accesso. Quando faremo clic sul pulsante Logout, dovremmo assicurarci che il cookie venga rimosso dal browser del 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;

    /**
    * Implementazione del servlet della classe 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

  7. Sessione in Java Servlet – HttpSession

    L’API Servlet fornisce la gestione della sessione tramite l’interfaccia HttpSession. Possiamo ottenere la sessione dall’oggetto HttpServletRequest utilizzando i seguenti metodi. HttpSession ci consente di impostare gli oggetti come attributi che possono essere recuperati nelle richieste future.

    1. HttpSession getSession() – Questo metodo restituisce sempre un oggetto HttpSession. Restituisce l’oggetto sessione associato alla richiesta, se la richiesta non ha una sessione associata, quindi ne crea una nuova e la restituisce.
    2. HttpSession getSession(boolean flag) – Questo metodo restituisce l’oggetto HttpSession se la richiesta ha una sessione altrimenti restituisce null.

    Alcuni dei metodi importanti di HttpSession sono:

    1. String getId() – Restituisce una stringa contenente l’identificatore univoco assegnato a questa sessione.
    2. Object getAttribute(String name) – Restituisce l’oggetto associato al nome specificato in questa sessione, o null se nessun oggetto è associato al nome. Altri metodi per lavorare con gli attributi della sessione sono getAttributeNames(), removeAttribute(String name) e setAttribute(String name, Object value).
    3. long getCreationTime() – Restituisce il tempo in cui questa sessione è stata creata, misurato in millisecondi dalla mezzanotte del 1 ° gennaio 1970 GMT. Possiamo ottenere l’ultimo tempo di accesso con il metodo getLastAccessedTime().
    4. setMaxInactiveInterval(int interval) – Specifica il tempo, in secondi, tra le richieste del client prima che il contenitore servlet invalidi questa sessione. Possiamo ottenere il valore del timeout della sessione dal metodo getMaxInactiveInterval().
    5. ServletContext getServletContext() – Restituisce l’oggetto ServletContext per l’applicazione.
    6. boolean isNew() – Restituisce true se il client non conosce ancora la sessione o se il client sceglie di non partecipare alla sessione.
    7. void invalidate() – Annulla questa sessione quindi scollega tutti gli oggetti ad essa collegati.

    Quando utilizziamo il metodo HttpServletRequest getSession() e crea una nuova richiesta, crea il nuovo oggetto HttpSession e aggiunge anche un Cookie all’oggetto di risposta con nome JSESSIONID e valore come ID sessione. Questo cookie viene utilizzato per identificare l’oggetto HttpSession in ulteriori richieste dal client. Se i cookie sono disabilitati sul lato client e stiamo usando il rewriting URL, allora questo metodo utilizza il valore jsessionid dall’URL della richiesta per trovare la sessione corrispondente. Il cookie JSESSIONID viene utilizzato per il tracciamento della sessione, quindi non dovremmo usarlo per i nostri scopi applicativi per evitare eventuali problemi correlati alla sessione. Vediamo un esempio di gestione della sessione utilizzando l’oggetto HttpSession. Creeremo un progetto web dinamico in Eclipse con il contesto servlet come ServletHttpSessionExample. La struttura del progetto sarà simile all’immagine sottostante. login.html è lo stesso dell’esempio precedente e definito come pagina di benvenuto per l’applicazione in web.xml LoginServlet servlet creerà la sessione e imposterà attributi che possiamo utilizzare in altre risorse o nelle richieste future.

    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;
    
    /**
     * Implementazione del servlet della 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 {
    
    		// ottenere i parametri della richiesta per userID e password
    		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");
    			//impostare la sessione con scadenza in 30 minuti
    			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>Nome utente o password errati.</font>");
    			rd.include(request, response);
    		}
    
    	}
    
    }
    

    Il nostro codice LoginSuccess.jsp è il seguente.

    <%@ 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

  8. html

    Gestione della sessione in Java Servlet – Riscrittura URL

    Come abbiamo visto nella sezione precedente, possiamo gestire una sessione con HttpSession, ma se disabilitiamo i cookie nel browser, non funzionerà perché il server non riceverà il cookie JSESSIONID dal client. L’API Servlet fornisce il supporto per la riscrittura dell’URL che possiamo utilizzare per gestire la sessione in questo caso. La cosa migliore è che dal punto di vista della codifica, è molto facile da usare e coinvolge un solo passaggio – la codifica dell’URL. Un’altra cosa positiva della codifica degli URL del Servlet è che è un approccio di fallback e si attiva solo se i cookie del browser sono disabilitati. Possiamo codificare l’URL con il metodo encodeURL() di HttpServletResponse e se dobbiamo reindirizzare la richiesta a un’altra risorsa e vogliamo fornire informazioni sulla sessione, possiamo utilizzare il metodo encodeRedirectURL(). Creeremo un progetto simile a quello precedente tranne che utilizzeremo metodi di riscrittura dell’URL per assicurarci che la gestione della sessione funzioni correttamente anche se i cookie sono disabilitati nel browser. La struttura del progetto ServletSessionURLRewriting in Eclipse appare come nell’immagine seguente.

    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;
    
    /**
     * Implementazione del servlet della classe di accesso
     */
    @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 {
    
    		// ottieni i parametri della richiesta per userID e password
    		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");
    			// imposto la sessione con scadenza in 30 minuti
    			session.setMaxInactiveInterval(30*60);
    			Cookie userName = new Cookie("user", user);
    			response.addCookie(userName);
    			// Ottieni la stringa URL codificata
    			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>Sia il nome utente che la password sono errati.</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>Pagina di successo del login</title>
    </head>
    <body>
    <%
    // permetti l'accesso solo se esiste una sessione
    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>Ciao <%=userName %>, accesso riuscito. Il tuo ID sessione=<%=sessionID %></h3>
    <br>
    Utente=<%=user %>
    <br>
    <!-- è necessario codificare tutti gli URL dove vogliamo passare le informazioni della sessione -->
    <a href="<%=response.encodeURL("CheckoutPage.jsp") %>">Pagina di checkout</a>
    <form action="<%=response.encodeURL("LogoutServlet") %>" method="post">
    <input type="submit" value="Logout" >
    </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>Pagina di successo del login</title>
    </head>
    <body>
    <%
    String userName = null;
    // permetti l'accesso solo se esiste una sessione
    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>Ciao <%=userName %>, effettua il checkout.</h3>
    <br>
    <form action="<%=response.encodeURL("LogoutServlet") %>" method="post">
    <input type="submit" value="Logout" >
    </form>
    </body>
    </html>
    

    package com.journaldev.servlet.session;

    import java.io.IOException;

    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import

Ecco tutto per la gestione delle sessioni nelle servlet Java, esamineremo i Filtri e i Listener delle Servlet e i Cookie in futuri articoli. Aggiornamento: Controlla il prossimo articolo della serie Filtro Servlet.

Scarica i Progetti

Source:
https://www.digitalocean.com/community/tutorials/java-session-management-servlet-httpsession-url-rewriting