12. Webanwendung MVC [personne] – Version 7
12.1. Einleitung
In dieser Version gehen wir davon aus, dass es Client-Browser geben kann, die Folgendes unterbunden haben:
- die Rücksendung von Cookies, die vom Server gesendet werden,
- die Ausführung von JavaScript-Code, der in den angezeigten HTML-Seiten eingebettet ist
Dennoch möchten wir, dass auch diese Art von Browsern unsere Anwendung nutzen kann. Punkt 2 führt uns zurück zur Version 2 unserer Anwendung, da JavaScript erst ab Version 3 verwendet wurde. In Version 2 funktionierte die Anwendung ohne JavaScript, sodass Punkt 2 damit gelöst ist.
Punkt 1 kann schwierig zu handhaben sein oder auch nicht. Version 6 unserer Anwendung funktionierte ohne Cookies. Durch die Zusammenführung der Versionen 2 und 6 erzielen wir das gewünschte Ergebnis. Wir fügen eine zusätzliche Anforderung hinzu: Die Anwendung muss eine Sitzung verwalten. Diese Anforderung ist nicht sinnlos. In einer Anwendung, in der sich Benutzer authentifizieren müssen, muss der Server das Paar (Benutzername/Passwort) des Benutzers speichern, damit dieser sich nicht bei jeder angeforderten Seite erneut authentifizieren muss.
Bisher haben wir drei Lösungen verwendet, um Informationen während des Client-Server-Austauschs zu speichern:
- die Sitzung
- Cookies
- versteckte Felder.
Lösung 2 kann ausgeschlossen werden, da der Browser die Verwendung von Cookies möglicherweise deaktiviert hat.
Lösung 3 entspricht der zuvor untersuchten Version 6. Sie kann aus Sicherheitsgründen nicht verwendet werden. Wenn das Paar (Benutzername/Passwort) in jeder an den Browser gesendeten Seite enthalten ist, bedeutet dies, dass es bei jedem Austausch zwischen Client und Server über das Netzwerk übertragen wird. Dies ist für die Sicherheit der Anwendung nicht gut. Man könnte daher in Erwägung ziehen, das Protokoll HTTPS zu verwenden, das den Datenverkehr zwischen Client und Server verschlüsselt. Die Verwendung dieses Protokolls für jede Seite der Anwendung würde jedoch die Serverlast erhöhen.
Man könnte Lösung 1 ausschließen wollen, da sie ebenfalls auf Cookies basiert. Beim ersten Austausch zwischen Client und Server sendet der Server dem Client ein Session-Token, das dieser bei jeder neuen Anfrage an den Server zurücksendet. Dank dieses Tokens kann der Server seinen Client erkennen und ihm Informationen zuweisen, die er bei einem früheren Austausch gespeichert hatte. Das Session-Token wird vom Server in einem Cookie gesendet. Ein Browser, der Cookies nicht deaktiviert hat, kann dieses Cookie bei seinen folgenden Anfragen an den Server zurücksenden. Hat er Cookies deaktiviert, steht ihm eine andere Lösung zur Verfügung: Er kann das Session-Token in die angeforderte URL einfügen. Dies sehen wir nun, wenn wir die Untersuchung der Datei „[index.jsp]“ aus Version 4 fortsetzen:
<%@ 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"/>
Zur Erinnerung: Zeile 5 oben leitet den Client zur URL [/personne4/main?jsessionid=XX] weiter, wobei XX das Session-Token ist, wie der folgende Screenshot zeigt, der nach dem Aufruf der URL [http://localhost:8080/personne4] erstellt wurde:

Schauen wir uns die Funktionsweise des Tags <c:redirect> in Bezug auf das Session-Token einmal genauer an. Nehmen wir einen Browser, in dem Cookies akzeptiert werden. Im Folgenden konfigurieren wir den Firefox-Browser:

In [1] aktivieren wir Cookies und in [2] löschen wir bereits vorhandene Cookies, um von einer bekannten Situation auszugehen. Anschließend rufen wir die URL [http://localhost:8080/personne4] auf. Wir erhalten folgende Antwort:

Die ursprüngliche Anfrage des Kunden lautete wie folgt:
Es sei lediglich angemerkt, dass der Client kein Session-Cookie sendet. Die vom Server gesendete Antwort HTTP lautet wie folgt:
- Zeile 1: Der Server fordert den Client auf, sich umzuleiten
- Zeile 3: Der Server sendet ein Session-Token, das mit dem Attribut [JSESSIONID] verknüpft ist
- Zeile 4: Die Weiterleitungs-URL enthält das Session-Token. Das <c:redirect>-Tag hat es dort eingefügt, da der Client kein Session-Cookie gesendet hatte.
Der Browser, der zur Weiterleitung aufgefordert wurde, hat daraufhin folgende Anfrage gestellt:
- Zeile 1: Er fragt die Weiterleitungs-URL ab, einschließlich des Session-Tokens. Deshalb zeigt der Browser auf dem Screenshot diese URL an.
- Zeile 10: Der Browser sendet das Session-Token zurück, das ihm der Server im vorherigen Austausch gesendet hat. Dies entspricht der normalen Funktionsweise von Cookies, wenn diese im Client-Browser zugelassen sind. Ist dies nicht der Fall, werden empfangene Cookies nicht zurückgesendet.
Der Server hat auf diese zweite Anfrage Folgendes geantwortet:
Er hat die angeforderte Seite gefunden und sendet sie nun. Man beachte, dass er das Session-Token nicht mehr mitsendet. Dies entspricht der normalen Funktionsweise eines Session-Tokens: Es wird vom Server einmalig in Form eines Cookies an den Browser gesendet, und der Browser sendet es anschließend bei jeder Anfrage zurück, um sich identifizieren zu lassen.
Rufen wir nun mit demselben Browser die URL [http://localhost:8080/personne4] erneut auf, indem wir sie manuell eingeben. Wir erhalten dann die folgende Seite:

Man stellt fest, dass die vom Browser angezeigte URL das Session-Token nicht mehr enthält. Sehen wir uns den ersten Austausch zwischen Client und Server an:
Der Browser hat folgende Anfrage gestellt:
Es handelt sich um genau dieselbe Anfrage wie beim letzten Mal, allerdings mit einem Unterschied: In Zeile 10 sendet der Browser das Session-Token zurück, das er beim allerersten Austausch erhalten hatte. Auch dies ist das normale Verhalten, wenn die Cookies des Browsers aktiviert sind.
Der Server hat die folgende Antwort gesendet:
Er fordert den Client auf, sich umleiten zu lassen. Da er ein Session-Token vom Client erhalten hat, setzt er die Sitzung fort und sendet kein neues Session-Token. Aus demselben Grund fügt das <c:redirect>-Tag dieses Session-Token nicht in die Weiterleitungs-URL ein. Deshalb enthält die im obigen Screenshot angezeigte URL kein Session-Token.
Daraus lässt sich folgende Regel ableiten: Das <c:redirect>-Tag fügt das Session-Token nur dann in die Weiterleitungs-URL ein, wenn der Client den Header HTTP nicht gesendet hat:
Diese Regel gilt auch für das <c:url>-Tag, auf das wir später noch eingehen werden.
Was passiert in einem Browser, in dem Cookies deaktiviert sind? Probieren wir es aus. Zunächst setzen wir den Browser zurück:

In [1] deaktivieren wir Cookies und in [2] löschen wir die bereits vorhandenen, um von einer bekannten Situation auszugehen. Anschließend rufen wir die URL [http://localhost:8080/personne4] auf. Wir erhalten folgende Antwort:

Wir erhalten das gleiche Ergebnis wie zuvor. Die Datenaustausche HTTP sind jedoch nicht genau dieselben:
- Zeilen 1–9: Anfrage Nr. 1 des Browsers. Er sendet kein Sitzungs-Cookie.
- Zeilen 11–17: Die Antwort des Servers, der ihn auffordert, zu einer anderen URL weiterzuleiten. Er sendet ein Session-Cookie. Zeile 13: Das <c:redirect>-Tag hat das Token in die Weiterleitungs-URL in Zeile 14 eingebunden.
- Zeilen 19–27: Anfrage Nr. 2 des Browsers. Er sendet das soeben vom Server gesendete Sitzungs-Cookie nicht zurück, da seine Cookies deaktiviert sind.
- Zeilen 29–33: Die Antwort des Servers. Es ist festzustellen, dass der Server, obwohl der Browser ihm kein Sitzungscookie gesendet hat, dennoch keine neue Sitzung startet, wie man es hätte erwarten können. Dies zeigt sich daran, dass er den Header HTTP [Set-Cookie] nicht wie in Zeile 13 sendet. Das bedeutet, dass er die vorherige Sitzung fortsetzt. Er konnte diese dank des Sitzungstokens wiederfinden, das in der vom Browser in Zeile 19 angeforderten URL enthalten war.
Es ist zu beachten, dass der Server eine Sitzung verfolgt, indem er das vom Client gesendete Sitzungstoken auf zwei verschiedene Arten abruft:
- im vom Kunden gesendeten Header „HTTP [Set-Cookie]“
- in der vom Kunden angeforderten URL
Rufen wir nun mit demselben Browser die URL „[http://localhost:8080/personne4]“ erneut auf, indem wir sie manuell eingeben, so wie es zuvor geschehen ist, als Cookies noch zugelassen waren. Daraufhin wird folgende Seite angezeigt:

Das Ergebnis unterscheidet sich von dem, das man erhielt, als Cookies noch zugelassen waren: Das Session-Token ist in der vom Browser angezeigten URL enthalten. Lassen Sie uns dieses Ergebnis erklären, ohne die stattgefundenen Datenaustausche HTTP genauer zu untersuchen:
[cookies autorisés]
- Bei der zweiten Anfrage der URL [http://localhost:8080/personne4] hatte der Client-Browser das Sitzungs-Cookie zurückgesendet, das er bei der ersten Anfrage derselben URL vom Server erhalten hatte. Das <c:redirect>-Tag hatte das Sitzungs-Token daher nicht in die Weiterleitungsadresse aufgenommen.
[cookies inhibés]
- Bei der zweiten Anfrage der URL [http://localhost:8080/personne4] sendet der Client-Browser das Sitzungs-Cookie, das er bei der ersten Anfrage derselben URL vom Server erhalten hatte, nicht, da seine Cookies deaktiviert sind. Das <c:redirect>-Tag fügt daher das Session-Token in die Weiterleitungsadresse ein. Deshalb ist es auf dem obigen Screenshot zu sehen.
Mit den Tags <c:redirect> und <c:url> lässt sich das Session-Token in URLs einbinden. Dies ist die hier vorgeschlagene Lösung.
12.2. Das Eclipse-Projekt
Um das Eclipse-Projekt [mvc-personne-07] für die Webanwendung [/personne7] zu erstellen, duplizieren wir das Projekt [mvc-personne-06] gemäß der in Abschnitt 6.2 beschriebenen Vorgehensweise.
![]() | ![]() |
12.3. Konfiguration der Webanwendung [personne7]
Die Datei web.xml der Anwendung /personne7 lautet wie folgt:
<?xml version="1.0" encoding="UTF-8"?>
...
<display-name>mvc-personne-07</display-name>
...
Diese Datei ist identisch mit der der vorherigen Version, abgesehen von Zeile 3, in der sich der Anzeigename der Webanwendung in [mvc-personne-07] geändert hat. Die Startseite [index.jsp] bleibt unverändert.
...
<c:redirect url="/do/formulaire"/>
12.4. Der Code der Ansichten
Die Ansichten [formulaire, réponse, erreurs] sind wieder so wie in Version 2, c.a.d, ohne JavaScript. Sie behalten jedoch die Tags JSTL der letzten Versionen bei.
12.4.1. Die Ansicht [formulaire]

Die mit JavaScript-Code verbundenen Schaltflächen wurden entfernt.
[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>
- Zeile 14: Die Ziel-URL von POST wird mit dem Tag <c:url> geschrieben, damit das Session-Token darin enthalten ist, falls der Client ein Browser ist, der den Header HTTP [Cookie] nicht sendet.
- Das Formular verfügt über zwei Schaltflächen vom Typ [submit]: [Envoyer] (Zeile 28) und [Effacer] (Zeile 30). Beide Schaltflächen tragen denselben Namen: bouton. Beim Klicken auf POST sendet der Browser den Parameter:
- button=Senden, wenn der POST-Aufruf durch die Schaltfläche [Senden] ausgelöst wurde
- button=Löschen, wenn der POST-Aufruf durch die Schaltfläche [Löschen] ausgelöst wurde
Anhand dieses Parameters können wir die genaue Aktion festlegen, da die URL [/do/validationFormulaire] nun zwei unterschiedlichen Aktionen entspricht.
12.4.2. Die Ansicht [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>
- Zeile 24: Die Ziel-URL von HREF wird mit dem Tag <c:url> geschrieben, damit das Session-Token darin enthalten ist, falls der Client ein Browser ist, der den Header HTTP [Cookie] nicht sendet.
12.4.3. Die Ansicht [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>
- Zeile 18: Die Ziel-URL von HREF wird mit dem Tag <c:url> geschrieben, damit das Session-Token darin enthalten ist, falls der Client ein Browser ist, der den Header HTTP [Cookie] nicht sendet.
Der Leser wird gebeten, diese neuen Ansichten nach dem in den vorherigen Versionen beschriebenen Prinzip zu testen.
12.5. Der Controller [ServletPersonne]
Der Controller [ServletPersonne] der Webanwendung [/personne7] lautet wie folgt:
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 | |
- Zeile 35: Die Aktion [/retourFormulaire] wird von einem GET ausgeführt und nicht mehr von einem POST wie in der vorherigen Version.
- Zeilen 70–87: Die Aktion [/validationFormulaire] wird durch eine Aktion POST ausgelöst, die durch einen Klick aufeiner der Schaltflächen [Envoyer] oder [Effacer] in der Ansicht [formulaire] ausgelöst wird. Die Methode [doValidationFormulaire] lässt diese beiden Fälle von zwei verschiedenen Methoden bearbeiten.
- Zeilen 90–103: Die Methode [doEnvoyer] entspricht der Methode [doValidationFormulaire] aus der vorherigen Version. Die eingegebenen Daten werden in die Sitzung geschrieben (Zeilen 96–98), während sie in der vorherigen Version in die Abfrage geschrieben wurden.
- Zeilen 58–67: Die neue Methode [doEffacer] soll ein leeres Formular anzeigen. Man könnte die Methode [doInit] aufrufen, die diese Aufgabe bereits übernimmt. Hier wird die Gelegenheit genutzt, um auch die Elemente [nom, age] aus der Sitzung zu löschen, damit diese weiterhin den aktuellen Stand des Formulars widerspiegelt.
- Zeilen 50–55: Fordern die Anzeige der Ansicht [formulaire] an, ohne dass das Modell dieser Ansicht offensichtlich initialisiert wird. Dieses Modell besteht tatsächlich aus den Elementen [nom, age], die sich bereits in der Sitzung befinden. Es sind keine weiteren Schritte erforderlich.
12.6. Tests
Starten oder starten Sie Tomcat neu, nachdem Sie das Eclipse-Projekt [personne-mvc-07] darin integriert haben, und rufen Sie dann die URL [http://localhost:8080/personne7] mit einem Browser auf, bei dem Cookies deaktiviert und bereits vorhandene gelöscht wurden. Sie erhalten folgende Antwort:

Der vom Browser empfangene Quellcode lautet wie folgt:
Zeile 1: Das Session-Token befindet sich in der Ziel-URL von POST.
Füllen wir das Formular aus und bestätigen wir es:

Der vom Browser empfangene Quellcode lautet wie folgt:
In Zeile 3 befindet sich das Session-Token in der Ziel-URL des Links.

