Add lesson 8
[hacks/simpleWebSlides.git] / prog_internet / prog_internet_08.xhtml
1 <?xml version="1.0" encoding="utf-8" ?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
4           >
5 <html xmlns="http://www.w3.org/1999/xhtml" >
6   <head>
7     <title>PHP : Sessions et persistance</title>
8
9     <meta http-equiv="Content-Type"
10           content="text/html; charset=utf-8" />
11     <meta name="copyright"
12           content="Copyright &#169; 2013 Kim Nguyễn" />
13
14     <!-- Load jQuery -->
15     <script src="../jquery-2.0.3.min.js" type="text/javascript" ></script>
16     <script src="../libs/raphael-min.js" type="text/javascript" ></script>
17     <!-- Load the library -->
18     <script src="../simpleWebSlides.js" type="text/javascript" ></script>
19
20     <link rel="stylesheet" href="../simpleWebSlides.css" type="text/css"  media="all" />
21     <!-- Load a custom Theme, the class-element marks this style-sheet
22          a "theme" that can be swtiched dynamicaly -->
23     <link class="sws-theme" rel="stylesheet"  title="U-Psud style"  href="../themes/uPsud.css" type="text/css" />
24
25     <!-- Customize some templates and initialize -->
26
27     <script type="text/javascript">
28       SWS.Config['sws-slide-change'] = SWS.Effects.slideChangeFadeOutIn;
29       SWS.Config['sws-object-deactivate'] =  SWS.Effects.objectDeactivateFadeOut;
30       SWS.Config['sws-object-activate'] = SWS.Effects.objectActivateFadeIn;
31
32       //Ensures that we load SWS at the very end, after MathJax has
33       //been initialized
34
35       $(window).load(SWS.Presentation.init);
36     </script>
37   </head>
38   <body>
39     <a href="prog_internet_06.xhtml" class="sws-previous"/>
40     <div class="sws-slide sws-cover sws-option-nofooter">
41       <h1>Programmation Internet</h1>
42       <h1>Cours 8</h1>
43       <a href="mailto:kn@lri.fr">kn@lri.fr</a><br/>
44       <a href="http://www.lri.fr/~kn/">http://www.lri.fr/~kn</a>
45     </div>
46
47     <h1>En-tête de requêtes HTTP</h1>
48
49     <div class="sws-slide">
50       <h1>Retour sur le protocole HTTP</h1>
51       <ul><li><em>Client : </em>
52 <code>GET <em>/~kn/index.html</em> HTTP/1.1
53 Host: www.lri.fr
54 </code> </li>
55 <li><em>Serveur : </em><br/>
56   <code style="display:inline-block;width:60%;vertical-align:top;">HTTP/1.1 200 OK
57 Server: nginx/1.4.1 (Ubuntu)
58 Date: Sun, 17 Nov 2013 16:44:48 GMT
59 Content-Type: <em>text/html</em>
60 Content-Length: 2038
61 <![CDATA[
62 <html>
63   <head><title>Homepage</title> </head>
64   <body>
65     …
66 ]]>
67   </code>
68 <code style="display:inline-block;
69              black;width:30%;vertical-align:top;">} ← <em>code de retour</em>
70
71
72 } ← <em>type de contenu</em>
73 } ← <em>longueur du contenu</em>
74 <span style="font-size:400%;vertical-align:middle;">}</span> <span>←</span> <em>contenu (2038 octets)</em>
75 </code>
76 </li>
77       </ul>
78     </div>
79
80     <div class="sws-slide">
81       <h1>Retour sur le protocole HTTP (2)</h1>
82       <ul><li><em>Client : </em>
83 <code>GET <em>/~kn/fichier.pdf</em> HTTP/1.1
84 Host: www.lri.fr
85 </code> </li>
86 <li><em>Serveur : </em><br/>
87   <code >HTTP/1.1 200 OK
88 Server: nginx/1.4.1 (Ubuntu)
89 Date: Sun, 17 Nov 2013 16:44:48 GMT
90 Content-Type: <em>application/pdf</em>
91 Content-Length: 103449
92 <![CDATA[
93 %PDF-1.2
94 %
95 8 0 obj
96 <</Length 9 0 R/Filter /FlateDecode>>
97 stream
98 ………
99  ]]>
100   </code>
101
102 </li>
103       </ul>
104     </div>
105 <div class="sws-slide">
106 <h1>Modifier le <em>content-type</em> en PHP</h1>
107 <p>Fichier <tt>notes_csv.php</tt>:</p>
108 <code>  &lt;?php<em>
109     header('Content-type: application/csv');
110     header('Content-Disposition: attachement; filename="notes.csv"');</em>
111     echo "Nom, Note\n";
112     foreach ($NOTES as $nom => $note)
113        echo $nom . ", " . $note . "\n";
114
115   ?&gt;</code>
116 <p class="sws-pause"><b style="color:red">&#9888; Attention!</b></p>
117 <ul>
118   <li>Les appels à la fonction <em><tt>header()</tt></em> doivent se
119   trouver <s>avant</s> le premier <tt>echo()</tt> du code PHP</li>
120   <li>
121     Le code PHP doit générer (avec <tt>echo()</tt>) du contenu
122     compatible avec le type annoncé (et pas du HTML)
123   </li>
124 </ul>
125 </div>
126
127 <div class="sws-slide">
128 <h1>Quelques en-tête utiles</h1>
129 <p>En tête utilisés par le serveur dans ses réponses</p>
130 <dl>
131   <dt><tt>Content-type</tt></dt><dd>type MIME du contenu envoyé par le
132   serveur</dd>
133   <dt><tt>Content-Disposition</tt></dt><dd>permet de mentionner un nom de
134   fichier : <em><tt>attachment; filname="foobar.baz"</tt></em></dd>
135   <dt><tt>Cache-Control</tt></dt><dd>permet de forcer le client à
136   retélécharger la page: <em><tt>no-cache, must-revalidate</tt></em>
137   </dd>
138   <dt><tt>Last-Modified</tt></dt><dd>date de dernière modification du
139   contenu demandé</dd>
140 </dl>
141 <p>En tête utilisés par le client dans ses requêtes</p>
142 <dl>
143   <dt><tt>Range</tt></dt><dd>permet de ne récupérer qu'un intervale
144   d'octets donné dans un fichier: <em><tt>bytes=500-999</tt></em>
145   </dd>
146   …
147 </dl>
148
149 </div>
150 <div class="sws-slide">
151   <h1>Retour sur le protocole HTTP (3)</h1>
152   <p>On rappelle que HTTP est un protocole <em><i>stateless</i></em>
153   (sans état, <i>i.e.</i> le serveur Web ne conserve pas d'information
154   entre les connexions). Quel problème cela pose-t-il ?</p>
155   <ul >
156     <li class="sws-pause">Pas de partage d'information entre plusieur
157     pages</li>
158     <li class="sws-pause">Pas de mécanisme de reprise sur panne
159     </li>
160     <li class="sws-pause">Pas de persistance de l'information</li>
161     <li class="sws-pause">Pas d'authentification (impossible de savoir
162     que deux connexions successives ont été faites par le même
163     client)</li>
164   </ul>
165   <p class="sws-pause">⇒ difficle de réaliser une « application »
166     moderne répartie sur plusieurs pages</p>
167 </div>
168
169 <h1>Cookies</h1>
170 <div class="sws-slide">
171 <h1>Cookies</h1>
172 <p>Un <em><i>cookie</i></em> est un packet de données envoyé par le
173   serveur, stocké par le client (navigateur Web) et renvoyé au serveur
174   lors d'une nouvelle connexion. Les propriétés d'un cookie sont:
175 </p>
176 <dl>
177   <dt>Son nom</dt><dd>une chaîne de caractères</dd>
178   <dt>Sa valeur</dt><dd>une chaîne de caraceres</dd>
179   <dt>Sa durée de vie</dt><dd>jusqu'à la fin de la « session » ou pour
180   une période donnée</dd>
181   <dt>Son domaine</dt><dd>Le nom du site web émetteur du cookie</dd>
182   <dt>Son chemin</dt><dd>Le sous-répertoire (par rapport à la racine
183   du site) pour lequel le cookie est valide</dd>
184 </dl>
185 <p><b style="color:red">&#9888; Attention!</b> seul le domaine qui a
186   déposé le cookie est capable de le relire</p>
187 </div>
188 <div class="sws-slide">
189 <h1>Cookies en PHP</h1>
190 <p>Créer ou mettre à jour un cookie sur le client:</p>
191 <code style="text-justify:center">
192                      setcookie(<em>$nom</em>, <em>$val</em>, <em>$date</em>);
193 </code>
194 <dl>
195   <dt><tt>$nom</tt></dt><dd>nom du cookie</dd>
196   <dt><tt>$val</tt></dt><dd>valeur du cookie</dd>
197   <dt><tt>$date</tt></dt><dd>date d'expiration en secondes
198   depuis <i>epoch</i> (1<sup>er</sup> janvier 1970 00:00:00)
199   ou <tt>NULL</tt> pour une expiration automatique.</dd>
200 </dl>
201 <p>(on peut récupérer le nombre de secondes depuis <i>epoche</i> avec
202   la fonction <tt>time()</tt>).<br/>
203   Exemple:
204 </p>
205 <code>  setcookie("mon_cookie", "42", time() + 3600 * 24 * 30);</code>
206 </div>
207
208 <div class="sws-slide">
209   <h1>Cookies en PHP</h1>
210   <p>On peut récupérer la valeur d'un cookie depuis PHP:
211   </p>
212   <code>                   <em>$_COOKIE["mon_cookie"]</em></code>
213   <p>Un cookie <tt>"foo"</tt> existe (<i>i.e.</i> a été défini
214   auparavant) si une entrée correspondante existe dans le tableau
215   global <em><tt>$_COOKIE</tt></em>. On peut tester qu'une entrée
216   existe dans un tableau avec <em><tt>isset()</tt></em>.
217   </p>
218   <p><b style="color:red">&#9888; Attention!</b> </p>
219   <ul>
220     <li>On ne peut pas écrire dans <em>$_COOKIE</em> (par
221     exemple <tt>$_COOKIE["foo"] = 42</tt>), il faut
222     utiliser <em><tt>setcookie()</tt></em>.
223     </li>
224     <li><em><tt>setcookie()</tt></em>
225     utilise <em><tt>header()</tt></em> et doit donc être appelé avant
226     le premier <em><tt>echo()</tt></em> du fichier.
227     </li>
228     <li>Pour effacer un cookie, on peut lui donner une date
229     d'expiration antérieure à l'instant présent (<tt>0</tt> par exemple)</li>
230   </ul>
231 </div>
232
233 <div class="sws-slide">
234   <h1>Avantages et inconvénients des cookies</h1>
235 <ul style="list-style-type:none;">
236   <li class="sws-pause"><b>+</b> stockage persistant</li>
237   <li class="sws-pause"><b>+</b> interface simple d'utilisation (une
238   variable pour la lecture et <tt>setcookie</tt> pour l'écriture)</li>
239   <li class="sws-pause"><b>-</b> limité en taille </li>
240   <li class="sws-pause"><b>-</b> limité en nombre par domaine</li>
241   <li class="sws-pause"><b>-</b> type de donnée limité à des chaînes
242   (on ne peut pas stocker un tableau PHP par exemple)</li>
243 <li class="sws-pause"><b>+/-</b> stocké sur le client</li>
244 </ul>
245 </div>
246 <h1>Sessions</h1>
247 <div class="sws-slide">
248 <h1>Sessions</h1>
249   <p>Une <em>session HTTP</em> est un ensemble de requêtes/réponses HTTP
250     entre un serveur et un <em>même</em> client.<br/>
251     Exemple d'un sondage en ligne:
252   </p>
253   <ol> <li>Le visiteur arrive sur la page <tt>q1.php</tt> en cliquant sur
254     le lien « commencer le sondage » (<em>Début de session</em>)
255     </li>
256     <li> Sur <tt>q1.php</tt>, l'utilisateur coche des choix dans un formulaire et appuie
257     sur un boutton de soumission qui l'envoie sur <tt>q2.php</tt>
258     </li>
259     <li>…</li>
260     <li> Sur <tt>q10.php</tt>, l'utilisateur coche des choix dans un
261     formulaire et appuie sur un bouton de soumission qui l'envoie
262     sur <tt>resultat.php</tt></li>
263     <li> Sur <tt>resultat.php</tt>, le résultat global du sondage (%
264       par question, nombre de participants jusqu'à présent etc...) est
265       affiché (<em>Fin de session</em>)
266     </li>
267   </ol>
268  
269 </div>
270 <div class="sws-slide">
271   <h1>Variables de session</h1>
272   <p>Pour programmer une application Web, on souhaîte avoir accès à
273   des <em>variables de session</em> c'est à dire des variables qui
274   sont:
275   </p>
276   <ul><li>Globale au serveur, et accessibles depuis plusieurs pages
277   PHP différentes</li>
278     <li>Spécifiques à un « utilisateur » (c'est à dire à une session
279     particulière)
280     </li>
281   </ul>
282   <p>Les variables de sessions sont donc propres à chaque client et
283   persistent le temp de la session (le temps de session est décidé par
284   le serveur)</p>
285 </div>
286 <div class="sws-slide">
287   <h1>Variables de session en PHP</h1>
288   <p>On initie une session avec la fonction:</p>
289   <code>                         <em>session_start();</em> </code>
290   <p>Une fois appelée, la variable <em><tt>$_SESSION</tt></em>
291     contient un tableau que l'on peut utiliser entre plusieurs
292     pages. Les valeurs contenues dans le tableau persistent jusqu'à la
293     fin de la session. Une session se termine:
294   </p>
295   <ul><li>Quand le client se déconnecte</li>
296     <li>Après un certain temps (« votre session a expiré, veuillez
297     vous reconnecter»)</li>
298     <li>Quand le code PHP
299     appelle <em><tt>session_end();</tt></em></li>
300   </ul>
301 <p><b style="color:red">&#9888;
302     Attention!</b> <em><tt>session_start()</tt></em> doit être appelé
303     avant le premier <tt>echo</tt> du fichier.</p>
304 </div>
305 <div class="sws-slide">
306   <h1>Variables de session en PHP (2)</h1>
307 <code style="border:  2pt dashed gray;margin:5pt;">
308   &lt;?php /* Fichier page1.php */
309     <em>session_start();
310     $_SESSION["Valeur"] = 42;</em>
311   ?&gt;
312   <![CDATA[<html>
313     <body>
314       Veuillez cliquer sur le <a href=]]><em>"page2.php"</em><![CDATA[>lien</a>
315     </body>
316   </html>
317 ]]></code>
318 <code style="border:  2pt dashed gray;margin:5pt;">  <![CDATA[<html>
319     <body>
320       La valeur est <?php]]> <em>echo $_SESSION["Valeur"];</em> <![CDATA[?>
321       <!-- affiche 42 -->
322     </body>
323   </html>
324 ]]></code>
325 </div>
326 <div class="sws-slide">
327   <h1>Avantages et inconvénients des session</h1>
328 <ul style="list-style-type:none;">
329   <li class="sws-pause"><b>+</b> Informations stockées sur le serveur</li>
330   <li class="sws-pause"><b>+</b> Pas de limite de taille</li>
331   <li class="sws-pause"><b>+</b> Pas limité à des chaînes de caractères</li>
332   <li class="sws-pause"><b>-</b> Valeurs perdues en fin de session</li>
333   <li class="sws-pause"><b>-</b> <s>Nécessite des cookies</s></li>
334 </ul>
335 </div>
336 <div class="sws-slide">
337   <h1>Sessions PHP: détails d'implantation</h1>
338   <div class="twocol">
339     <div><em>Coté client</em><br/>
340 <br/>
341 <br/>
342 <br/>
343 <br/>
344 <br/>
345 <br/>
346 <br/>
347 <br/>
348 <br/>
349 Connexion à une page PHP (envoie du cookie ("php_ssid", "12345"))
350
351
352     </div>
353     <div><em>Coté serveur (PHP)</em><br/>
354       <tt>session_start();</tt><br/>
355       - génération d'un ID unique "12345"<br/>
356       - dépot d'un cookie "php_ssid", valeur "12345", durée 10 minutes
357       - création dans un tableau global d'une entrée:<br/>
358         <tt>$_GLOBAL["12345"] = Array();</tt><br/>
359         <br/>
360         <tt>$_SESSION = $_GLOBAL[$_COOKIE["php_ssid"]]</tt>
361     </div>
362   </div>
363 </div>
364
365 <div class="sws-slide">
366   <h1>Dans la vraie Vie<sup>TM</sup></h1>
367   <p>Mélange de variables de sessions, cookies et bases de données.<br/>
368     Scénario réaliste: site de commerce en ligne
369   </p>
370   <ul>
371     <li>Login/mot de passe stocké dans
372       une <em style="color:blue;">BD</em> </li>
373     <li>Panier courant stocké dans une <em>variable de
374         session</em></li>
375     <li>Login, date de dernière visite, dernière page visitée stockés
376       dans un <em style="color:orange">en cookie</em></li>
377     </ul>
378   <p class="sws-pause">Pourquoi ?</p>
379   <ul>
380     <li><em style="color:blue;">BD</em>: information persistante,
381       côté serveur (mais la mise à jour, récupération de l'info est
382       coûteuse (en temps))
383     </li>
384     <li><em>Variables de sessions</em> : le panier n'a pas forcément
385       besoin d'être conservé entre deux sessions, mais on ne veut pas
386       que le client puisse fabriquer un panier frauduleux
387     </li>
388     <li><em style="color:orange">Cookie</em> : persistante à faible
389     coût (stocké sur le client), ce n'est pas grave si les
390     informations sont perdues ou corrompues
391     </li>
392   </ul>
393
394   </div>
395   </body>
396
397 </html>