12. Aplicación web MVC [personne] – versión 7
12.1. Introduction
En esta versión, suponemos que puede haber navegadores de los usuarios que hayan desactivado:
- el reenvío de las cookies que envía el servidor
- la ejecución de código JavaScript incrustado en las páginas HTML que se muestran
Sin embargo, queremos que este tipo de navegadores puedan utilizar nuestra aplicación. El punto 2 nos lleva de vuelta a la versión 2 de nuestra aplicación, ya que el JavaScript se comenzó a utilizar a partir de la versión 3. La versión 2 hacía funcionar la aplicación sin JavaScript, por lo que el punto 2 queda resuelto.
El punto 1 puede ser difícil o no de manejar. La versión 6 de nuestra aplicación funcionaba sin cookies. Al fusionar las versiones 2 y 6, obtenemos el resultado solicitado. Agregaremos una restricción adicional: la aplicación debe gestionar una sesión. No es una restricción sin sentido. En una aplicación donde los usuarios deben autenticarse, el servidor debe almacenar el par (identificador / contraseña) del usuario para evitar que tenga que autenticarse en cada página que solicite.
Hasta ahora hemos utilizado tres soluciones para almacenar información durante las comunicaciones entre el cliente y el servidor:
- la sesión
- las cookies
- los campos ocultos.
La solución 2 puede descartarse, ya que el navegador del cliente puede haber desactivado el uso de cookies.
La solución 3 es la de la versión 6 que analizamos anteriormente. No se puede utilizar por razones de seguridad. Si el par (nombre de usuario/contraseña) está encapsulado en cada página enviada al navegador, eso significa que transita por la red en cada intercambio entre el cliente y el servidor. Esto no es bueno para la seguridad de la aplicación. Entonces, se puede considerar el uso del protocolo HTTPS, que encripta los intercambios entre el cliente y el servidor. Sin embargo, utilizarlo para cada página de la aplicación aumentará la carga del servidor.
Podríamos querer descartar la solución 1 porque también se basa en cookies. Durante el primer intercambio entre el cliente y el servidor, el servidor envía al cliente un token de sesión que este último devolverá al servidor en cada nueva solicitud. Gracias a este token, el servidor podrá reconocer a su cliente y asignarle la información que había almacenado durante un intercambio anterior. El servidor envía el token de sesión en una cookie. El navegador que no haya desactivado las cookies puede devolverle esta cookie en sus solicitudes posteriores. Si ha desactivado las cookies, cuenta con otra solución: puede incluir el token de sesión en la URL que solicita. Esto es lo que vemos ahora al retomar el análisis del archivo [index.jsp] de la versión 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"/>
Recordemos que la línea 5 anterior redirige al cliente a la URL [/personne4/main?jsessionid=XX], donde XX es el token de sesión, tal como lo muestra la captura de pantalla a continuación, obtenida tras solicitar la URL [http://localhost:8080/personne4]:

Analicemos más a fondo el funcionamiento de la etiqueta <c:redirect> en lo que respecta al token de sesión. Tomemos como ejemplo un navegador en el que se aceptan cookies. A continuación, configuramos el navegador Firefox:

En [1], habilitamos las cookies y en [2] eliminamos las que ya existen para partir de una situación conocida. Luego solicitamos la URL [http://localhost:8080/personne4]. Obtenemos la siguiente respuesta:

La solicitud inicial del cliente, HTTP, fue la siguiente:
Cabe señalar simplemente que el cliente no envía una cookie de sesión. La respuesta HTTP enviada por el servidor es la siguiente:
- línea 1: el servidor le pide al cliente que se redirija
- línea 3: el servidor envía un token de sesión asociado al atributo [JSESSIONID]
- línea 4: la URL de redirección contiene el token de sesión. La etiqueta <c:redirect> lo colocó allí porque el cliente no había enviado una cookie de sesión.
El navegador, al que se le pidió que se redirigiera, realizó a continuación la siguiente solicitud:
- línea 1: solicita la URL de redirección, incluido el token de sesión. Por eso, en la captura de pantalla, el navegador muestra esa URL.
- línea 10: el navegador devuelve el token de sesión que el servidor le envió en el intercambio anterior. Este es el funcionamiento normal de las cookies cuando están habilitadas en el navegador del cliente. Si no es así, las cookies recibidas no se devuelven.
El servidor respondió lo siguiente a esta segunda solicitud:
Encontró la página que se le solicitó y la envía. Cabe señalar que ya no envía el token de sesión. Este es el funcionamiento normal del token de sesión: el servidor lo envía al navegador una sola vez en forma de cookie y el navegador lo reenvía posteriormente con cada solicitud para que lo reconozcan.
Ahora, con el mismo navegador, solicitemos nuevamente la URL [http://localhost:8080/personne4] escribiéndola manualmente. Entonces obtenemos la siguiente página:

Se observa que la URL que muestra el navegador ya no contiene el token de sesión. Veamos el primer intercambio entre el cliente y el servidor:
El navegador realizó la siguiente solicitud:
Es exactamente la misma solicitud que la vez anterior, pero con una diferencia: en la línea 10, el navegador devuelve el token de sesión que había recibido durante el primer intercambio. Una vez más, este es el funcionamiento normal si las cookies del navegador están activas.
El servidor envió la siguiente respuesta:
Le pide al cliente que se redirija. Como recibió un token de sesión del cliente, continúa con esa sesión y no envía un nuevo token de sesión. Por la misma razón, la etiqueta <c:redirect> no incluye este token de sesión en la URL de redirección. Por eso la URL que se muestra en la captura de pantalla anterior no tiene un token de sesión.
De todo esto se desprende la siguiente regla: la etiqueta <c:redirect> solo incluye el token de sesión en la URL de redirección si el cliente no ha enviado el encabezado HTTP:
Esta regla también se aplica a la etiqueta <c:url>, con la que nos encontraremos más adelante.
¿Qué sucede con un navegador en el que se han desactivado las cookies? Probemos. Primero, reiniciamos el navegador:

En [1], desactivamos las cookies y en [2] eliminamos las que ya existen para partir de una situación conocida. Luego solicitamos la URL [http://localhost:8080/personne4]. Obtenemos la siguiente respuesta:

Obtenemos el mismo resultado que antes. Sin embargo, los intercambios HTTP no son exactamente los mismos:
- líneas 1-9: la solicitud n.º 1 del navegador. No envía una cookie de sesión.
- líneas 11-17: la respuesta del servidor que le pide que se redirija a otra URL. Envía una cookie de sesión en la línea 13: la etiqueta <c:redirect> ha incluido el token en la URL de redirección de la línea 14.
- líneas 19-27: la solicitud n.º 2 del navegador. No devuelve la cookie de sesión que el servidor le acaba de enviar porque tiene desactivadas las cookies.
- líneas 29-33: la respuesta del servidor. Se puede observar que, aunque el navegador no le haya enviado una cookie de sesión, el servidor no inicia una nueva sesión como cabría esperar. Esto se ve en el hecho de que no envía el encabezado HTTP [Set-Cookie] como lo había hecho en la línea 13. Esto significa que continúa con la sesión anterior. Pudo recuperarla gracias al token de sesión presente en la URL solicitada por el navegador en la línea 19.
Cabe destacar que el servidor da seguimiento a una sesión recuperando el token de sesión enviado por el cliente de dos maneras posibles:
- en el encabezado HTTP [Set-Cookie] enviado por el cliente
- en la URL solicitada por el cliente
Ahora, con el mismo navegador, solicitemos nuevamente la URL [http://localhost:8080/personne4] escribiéndola manualmente, tal como se había hecho cuando las cookies estaban permitidas. Entonces obtenemos la siguiente página:

El resultado es diferente al obtenido cuando las cookies estaban permitidas: el token de sesión aparece en la URL que muestra el navegador. Explicaremos este resultado sin analizar los intercambios HTTP que tuvieron lugar:
[cookies autorisés]
- Durante la segunda solicitud de la URL [http://localhost:8080/personne4], el navegador del cliente había devuelto la cookie de sesión que había recibido del servidor durante la primera solicitud de esa misma URL. Por lo tanto, la etiqueta <c:redirect> no había incluido el token de sesión en la dirección de redirección.
[cookies inhibés]
- En la segunda solicitud de la URL [http://localhost:8080/personne4], el navegador del cliente no envía la cookie de sesión que recibió del servidor durante la primera solicitud de esa misma URL, ya que sus cookies están desactivadas. La etiqueta <c:redirect> incluye, por lo tanto, el token de sesión en la dirección de redirección. Por eso aparece en la captura de pantalla anterior.
Las etiquetas <c:redirect> y <c:url> permiten incluir el token de sesión en las URL. Esa es la solución que se propone aquí.
12.2. El proyecto de Eclipse
Para crear el proyecto de Eclipse [mvc-personne-07] de la aplicación web [/personne7], se duplicará el proyecto [mvc-personne-06] siguiendo el procedimiento descrito en el párrafo 6.2.
![]() | ![]() |
12.3. Configuración de la aplicación web [personne7]
El archivo web.xml de la aplicación /personne7 es el siguiente:
<?xml version="1.0" encoding="UTF-8"?>
...
<display-name>mvc-personne-07</display-name>
...
Este archivo es idéntico al de la versión anterior, salvo por la línea 3, donde el nombre de visualización de la aplicación web ha cambiado a [mvc-personne-07]. La página de inicio [index.jsp] no cambia.
...
<c:redirect url="/do/formulaire"/>
12.4. El código de las vistas
Las vistas [formulaire, réponse, erreurs] vuelven a ser lo que eran en la versión 2, c.a.d, sin JavaScript. Sin embargo, conservan las etiquetas JSTL de las últimas versiones.
12.4.1. La vista [formulaire]

Se han eliminado los botones asociados al código de 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>
- línea 14: la URL de destino de POST se escribe con la etiqueta <c:url> para que el token de sesión esté presente en caso de que el cliente sea un navegador que no envíe el encabezado HTTP [Cookie].
- El formulario tiene dos botones de tipo [submit]: [Envoyer] (línea 28) y [Effacer] (línea 30). Ambos botones tienen el mismo nombre: bouton. Al hacer clic en POST, el navegador enviará el parámetro:
- botón=Enviar si la solicitud POST fue iniciada por el botón [Enviar]
- botón=Borrar si la solicitud POST fue iniciada por el botón [Borrar]
Este parámetro nos ayudará a definir la acción exacta que se debe realizar, ya que la URL [/do/validationFormulaire] ahora corresponde a dos acciones distintas.
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>
- línea 24: la URL de destino de HREF se escribe con la etiqueta <c:url> para que el token de sesión esté presente en caso de que el cliente sea un navegador que no envíe el encabezado 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>
- línea 18: la URL de destino de HREF se escribe con la etiqueta <c:url> para que el token de sesión esté presente en caso de que el cliente sea un navegador que no envíe el encabezado HTTP [Cookie].
Se invita al lector a probar estas nuevas vistas siguiendo el principio visto en las versiones anteriores.
12.5. El controlador [ServletPersonne]
El controlador [ServletPersonne] de la aplicación web [/personne7] es el siguiente:
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 | |
- línea 35: la acción [/retourFormulaire] se realiza mediante un GET y ya no mediante un POST como en la versión anterior.
- líneas 70-87: la acción [/validationFormulaire] se realiza mediante una acción POST, que se activa al hacer clic enuno de los botones [Envoyer] o [Effacer] de la vista [formulaire]. El método [doValidationFormulaire] procesa estos dos casos mediante dos métodos distintos.
- líneas 90-103: el método [doEnvoyer] corresponde al método [doValidationFormulaire] de la versión anterior. Los datos ingresados se almacenan en la sesión (líneas 96-98), mientras que en la versión anterior se colocaban en la consulta.
- líneas 58-67: el nuevo método [doEffacer] debe mostrar un formulario en blanco. Se podría utilizar el método [doInit], que ya realiza esta tarea. Aquí, aprovechamos para borrar también los elementos [nom, age] de la sesión, de modo que esta siga reflejando el estado más reciente del formulario.
- líneas 50-55: solicitan que se muestre la vista [formulaire] sin una inicialización aparente de la plantilla de esta vista. Esta plantilla está compuesta, de hecho, por los elementos [nom, age] que ya se encuentran en la sesión. No es necesario hacer nada más.
12.6. Tests
Inicie o reinicie Tomcat después de haber integrado en él el proyecto de Eclipse [personne-mvc-07] y, a continuación, solicite la URL [http://localhost:8080/personne7] con un navegador en el que se hayan desactivado las cookies y se hayan eliminado las ya existentes. Se obtiene la siguiente respuesta:

El código fuente recibido por el navegador es el siguiente:
En la línea 1, el token de sesión se encuentra en la URL de destino de POST.
Rellenemos el formulario y validémo lo:

El código fuente que recibe el navegador es el siguiente:
Línea 3: el token de sesión se encuentra en la URL de destino del enlace.

