12. Applicazione web MVC [personne] – versione 7
12.1. Introduction
In questa versione, ipotizziamo che alcuni browser client possano aver disabilitato:
- l'invio dei cookie inviati dal server
- l'esecuzione del codice JavaScript incorporato nelle pagine HTML visualizzate
Vogliamo comunque che questo tipo di browser possa utilizzare la nostra applicazione. Il punto 2 ci riporta alla versione 2 della nostra applicazione, poiché il JavaScript è stato utilizzato a partire dalla versione 3. La versione 2 faceva funzionare l’applicazione senza JavaScript, quindi il punto 2 è risolto.
Il punto 1 può essere più o meno complesso da gestire. La versione 6 della nostra applicazione funzionava senza cookie. Unendo le versioni 2 e 6, otteniamo il risultato richiesto. Aggiungeremo un ulteriore vincolo: l’applicazione deve gestire una sessione. Non si tratta di un vincolo privo di senso. In un’applicazione in cui gli utenti devono autenticarsi, il server deve memorizzare la coppia (nome utente/password) dell’utente per evitare che questi debba autenticarsi ad ogni pagina richiesta.
Finora abbiamo utilizzato tre soluzioni per memorizzare le informazioni durante gli scambi client/server:
- la sessione
- i cookie
- i campi nascosti.
La soluzione 2 può essere scartata poiché il browser del cliente potrebbe aver disabilitato l'uso dei cookie.
La soluzione 3 è quella della versione 6 precedentemente esaminata. Non può essere utilizzata per motivi di sicurezza. Se la coppia (nome utente/password) è incapsulata in ogni pagina inviata al browser, ciò significa che transita sulla rete ad ogni scambio client/server. Ciò non è positivo per la sicurezza dell’applicazione. Si può quindi prendere in considerazione l’utilizzo del protocollo HTTPS, che crittografa gli scambi client/server. Tuttavia, utilizzarlo per ogni pagina dell’applicazione appesantirà il carico del server.
Si potrebbe voler scartare la soluzione 1 perché anch’essa si basa sui cookie. Durante il primo scambio client/server, il server invia al client un token di sessione che quest’ultimo rinvierà al server ad ogni nuova richiesta. Grazie a questo token, il server potrà riconoscere il proprio client e assegnargli le informazioni che aveva memorizzato durante uno scambio precedente. Il token di sessione viene inviato dal server all’interno di un cookie. Il browser che non ha disabilitato i cookie può rinviare questo cookie al server nelle richieste successive. Se invece ha disabilitato i cookie, dispone di un’altra soluzione: può includere il token di sessione nell’URL che richiede. È ciò che vediamo ora riprendendo l’analisi del file [index.jsp] della versione 4:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<c:redirect url="/main"/>
Ricordiamo che la riga 5 sopra riportata reindirizza il client all’URL [/personne4/main?jsessionid=XX], dove XX è il token di sessione, come mostra la schermata qui sotto ottenuta dopo aver richiesto l’URL [http://localhost:8080/personne4]:

Esaminiamo più da vicino il funzionamento del tag <c:redirect> per quanto riguarda il token di sessione. Prendiamo un browser in cui i cookie sono accettati. Di seguito, configuriamo il browser Firefox:

In [1] abilitiamo i cookie e in [2] eliminiamo quelli già presenti per partire da una situazione nota. Quindi richiediamo l’URL [http://localhost:8080/personne4]. Otteniamo la seguente risposta:

La richiesta iniziale del cliente HTTP era la seguente:
Si noti semplicemente che il cliente non invia alcun cookie di sessione. La risposta HTTP inviata dal server è la seguente:
- riga 1: il server chiede al cliente di reindirizzarsi
- riga 3: il server invia un token di sessione associato all’attributo [JSESSIONID]
- riga 4: l'URL di reindirizzamento contiene il token di sessione. Il tag <c:redirect> lo ha inserito perché il client non aveva inviato alcun cookie di sessione.
Il browser, a cui è stato richiesto di effettuare il reindirizzamento, ha quindi effettuato la seguente richiesta:
- riga 1: richiede l'URL di reindirizzamento, token di sessione incluso. Ecco perché, nella schermata, il browser visualizza questo URL.
- riga 10: il browser rinvia il token di sessione che il server gli ha inviato nello scambio precedente. Questo è il normale funzionamento dei cookie quando questi sono abilitati sul browser client. In caso contrario, i cookie ricevuti non vengono rinviati.
Il server ha risposto alla seconda richiesta con quanto segue:
Ha trovato la pagina richiesta e la invia. Si noti che non invia più il token di sessione. Questo è il normale funzionamento del token di sessione: viene inviato al browser una sola volta dal server sotto forma di cookie e il browser lo rinvia poi ad ogni richiesta per farsi riconoscere.
Ora, con lo stesso browser, richiediamo nuovamente l’URL [http://localhost:8080/personne4] digitandolo manualmente. Si ottiene quindi la seguente pagina:

Si nota che l’URL visualizzato dal browser non contiene più il token di sessione. Osserviamo il primo scambio client/server:
Il browser ha effettuato la seguente richiesta:
Si tratta esattamente della stessa richiesta della volta precedente, con una differenza: alla riga 10, il browser rinvia il token di sessione che aveva ricevuto durante il primissimo scambio. Ancora una volta, questo è il normale funzionamento se i cookie del browser sono attivi.
Il server ha inviato la seguente risposta:
Chiede al client di reindirizzarsi. Poiché ha ricevuto un token di sessione dal client, continua la sessione e non invia un nuovo token di sessione. Per lo stesso motivo, il tag <c:redirect> non include questo token di sessione nell'URL di reindirizzamento. Ecco perché l'URL visualizzato nella schermata qui sopra non contiene alcun token di sessione.
Da tutto ciò si ricava la seguente regola: il tag <c:redirect> include il token di sessione nell’URL di reindirizzamento solo se il client non ha inviato l’intestazione HTTP:
Questa regola vale anche per il tag <c:url>, che avremo modo di incontrare in seguito.
Cosa succede con un browser in cui i cookie sono stati disabilitati? Proviamo. Per prima cosa reinizializziamo il browser:

In [1] disabilitiamo i cookie e in [2] eliminiamo quelli già presenti per partire da una situazione nota. Quindi richiediamo l’URL [http://localhost:8080/personne4]. Otteniamo la seguente risposta:

Otteniamo lo stesso risultato di prima. Gli scambi HTTP non sono tuttavia esattamente gli stessi:
- righe 1-9: la richiesta n. 1 del browser. Non invia alcun cookie di sessione.
- righe 11-17: la risposta del server che gli chiede di reindirizzarsi verso un altro URL. Invia un cookie di sessione alla riga 13: il tag <c:redirect> ha incluso il token nell’URL di reindirizzamento alla riga 14.
- righe 19-27: la richiesta n. 2 del browser. Non rinvia il cookie di sessione che il server gli ha appena inviato perché i cookie sono disabilitati.
- righe 29-33: la risposta del server. Si può notare che, sebbene il browser non gli abbia inviato alcun cookie di sessione, il server non avvia comunque una nuova sessione come ci si sarebbe potuto aspettare. Ciò è evidente dal fatto che non invia l’intestazione HTTP [Set-Cookie] come aveva fatto alla riga 13. Ciò significa che prosegue la sessione precedente. È riuscito a recuperarla grazie al token di sessione presente nell’URL richiesto dal browser alla riga 19.
Da notare che il server gestisce una sessione recuperando il token di sessione inviato dal client in due modi possibili:
- nell’intestazione HTTP [Set-Cookie] inviata dal client
- nell’URL richiesto dal client
Ora, con lo stesso browser, richiediamo nuovamente l’URL [http://localhost:8080/personne4] digitandolo manualmente, come era stato fatto quando i cookie erano abilitati. Si ottiene quindi la seguente pagina:

Il risultato è diverso da quello ottenuto quando i cookie erano abilitati: il token di sessione è presente nell’URL visualizzato dal browser. Spieghiamo questo risultato senza analizzare gli scambi HTTP che hanno avuto luogo:
[cookies autorisés]
- durante la seconda richiesta dell’URL [http://localhost:8080/personne4], il browser client aveva rinviato il cookie di sessione che aveva ricevuto dal server durante la prima richiesta di quello stesso URL. Il tag <c:redirect> non aveva quindi incluso il token di sessione nell’indirizzo di reindirizzamento.
[cookies inhibés]
- durante la seconda richiesta dell'URL [http://localhost:8080/personne4], il browser client non invia il cookie di sessione ricevuto dal server durante la prima richiesta dello stesso URL, poiché i cookie sono disabilitati. Il tag <c:redirect> include quindi il token di sessione nell'indirizzo di reindirizzamento. Ecco perché lo si trova nella schermata sopra riportata.
I tag <c:redirect> e <c:url> consentono di includere il token di sessione negli URL. Questa è la soluzione proposta in questa sede.
12.2. Il progetto Eclipse
Per creare il progetto Eclipse [mvc-personne-07] dell’applicazione web [/personne7], si duplicherà il progetto [mvc-personne-06] seguendo la procedura descritta al paragrafo 6.2.
![]() | ![]() |
12.3. Configurazione dell'applicazione web [personne7]
Il file web.xml dell’applicazione /personne7 è il seguente:
<?xml version="1.0" encoding="UTF-8"?>
...
<display-name>mvc-personne-07</display-name>
...
Questo file è identico a quello della versione precedente, tranne che per la riga 3, dove il nome visualizzato dell'applicazione web è cambiato in [mvc-personne-07]. La pagina iniziale [index.jsp] rimane invariata.
...
<c:redirect url="/do/formulaire"/>
12.4. Il codice delle viste
Le viste [formulaire, réponse, erreurs] tornano ad essere quelle della versione 2, c.a.d, senza JavaScript. Tuttavia, mantengono i tag JSTL delle ultime versioni.
12.4.1. La vista [formulaire]

Sono stati rimossi i pulsanti associati al codice JavaScript.
[formulaire.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" action="<c:url value="validationFormulaire"/>" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="${nom}" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="${age}" type="text" size="3"></td>
</tr>
<tr>
</table>
<table>
<tr>
<td><input type="submit" name="bouton" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="submit" name="bouton" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
- riga 14: l'URL di destinazione di POST è scritto con il tag <c:url> in modo che il token di sessione vi sia presente nel caso in cui il client sia un browser che non invia l'intestazione HTTP [Cookie].
- Il modulo presenta due pulsanti di tipo [submit]: [Envoyer] (riga 28) e [Effacer] (riga 30). Entrambi i pulsanti hanno lo stesso nome: bouton. Al momento dell’esecuzione di POST, il browser invierà il parametro:
- pulsante=Invia se il POST è stato generato dal pulsante [Invia]
- pulsante=Cancella se il POST è stato generato dal pulsante [Cancella]
È questo parametro che ci aiuterà a definire l’azione esatta da eseguire, poiché l’URL [/do/validationFormulaire] corrisponde ora a due azioni distinte.
12.4.2. La vista [réponse]

[réponse.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Personne - réponse</h2>
<hr>
<table>
<tr>
<td>Nom</td>
<td>${nom}</td>
</tr>
<tr>
<td>Age</td>
<td>${age}</td>
</tr>
</table>
<br>
<a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
</body>
</html>
- riga 24: l'URL di destinazione di HREF è scritto con il tag <c:url> in modo che il token di sessione vi sia presente nel caso in cui il client sia un browser che non invia l'intestazione HTTP [Cookie].
12.4.3. La vista [erreurs]

[erreurs.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<ul>
<c:forEach var="erreur" items="${erreurs}">
<li>${erreur}</li>
</c:forEach>
</ul>
<br>
<a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
</body>
</html>
- riga 18: l'URL di destinazione di HREF è scritto con il tag <c:url> in modo che il token di sessione vi sia presente nel caso in cui il client sia un browser che non invia l'intestazione HTTP [Cookie].
Si invita il lettore a testare queste nuove viste seguendo il principio illustrato nelle versioni precedenti.
12.5. Il controller [ServletPersonne]
Il controller [ServletPersonne] dell’applicazione web [/personne7] è il seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
- riga 35: l’azione [/retourFormulaire] viene eseguita da un GET e non più da un POST come nella versione precedente.
- righe 70-87: l’azione [/validationFormulaire] viene eseguita da un’azione POST attivata cliccando suuno dei pulsanti [Envoyer] o [Effacer] della vista [formulaire]. Il metodo [doValidationFormulaire] gestisce questi due casi tramite due metodi distinti.
- righe 90-103: il metodo [doEnvoyer] corrisponde al metodo [doValidationFormulaire] della versione precedente. I dati inseriti vengono inseriti nella sessione (righe 96-98), mentre nella versione precedente venivano inseriti nella query.
- righe 58-67: il nuovo metodo [doEffacer] deve visualizzare un modulo vuoto. Si potrebbe ricorrere al metodo [doInit], che svolge già questa funzione. In questa occasione, si approfitta per cancellare anche gli elementi [nom, age] dalla sessione, in modo che questa continui a riflettere lo stato più recente del modulo.
- righe 50-55: richiedono la visualizzazione della vista [formulaire] senza un'apparente inizializzazione del modello di tale vista. Questo modello è infatti costituito dagli elementi [nom, age] già presenti nella sessione. Non è necessario fare altro.
12.6. Tests
Avviare o riavviare Tomcat dopo avervi integrato il progetto Eclipse [personne-mvc-07], quindi richiedere l’URL [http://localhost:8080/personne7] con un browser in cui sono stati disabilitati i cookie e sono stati eliminati quelli già esistenti. Si ottiene la seguente risposta:

Il codice sorgente ricevuto dal browser è il seguente:
Riga 1: il token di sessione si trova nell'URL di destinazione di POST.
Compiliamo il modulo e inviamolo:

Il codice sorgente ricevuto dal browser è il seguente:
Riga 3: il token di sessione è presente nell'URL di destinazione del link.

