Jérôme Cutrona

Version statique de l'intranet de Jérôme Cutrona - Rejoindre la version dynamique 🔒

Les exemples et corrections sont potentiellement non fonctionnels.

B.U.T. Informatique - IUT de Reims - Université de Reims

Protocole HTTP

Navigation

Objectifs de la séance

  • Se familiariser avec les éléments mis en œuvre entre le moment de la saisie d'une URL dans le navigateur et l'affichage du résultat
  • Découvrir la notion d'URI, d'URL
  • Utiliser la barre de développement du navigateur Web
  • Observer les échanges client/serveur avec protocole HTTP
  • Découvrir la structure des messages HTTP
  • Découvrir les en-têtes HTTP
  • Comprendre le contenu des messages HTTP
  • Comprendre les relations entre les formulaires GET ou POST et les requêtes HTTP construites
  • Écrire des requêtes HTTP
  • Effectuer des requêtes HTTP en ligne de commande
  • Écrire des requêtes HTTP portant des données
  • Comprendre les requêtes conditionnelles et leur utilité pour la gestion du cache

Introduction

Le protocole HTTP (Hypertext Transfer Protocol) est un protocole d'échange client-serveur de la couche application du modèle OSI. Il a été conçu dans les années 1990 pour répondre à la mise à disposition de ressources sur le World Wide Web. Ces ressources sont hébergées sur des serveurs Web (également appelés serveurs HTTP) et peuvent être récupérées à l'aide des URI et consultées sur les navigateurs Web (tels que Chrome, Firefox, Opera ou Edge pour les plus connus) mais également par les robots d'indexation des moteurs de recherche qui explorent et indexent le Web. La navigation entre les ressources est rendue possible par les hyperliens (ou liens hypertextes).

L'objectif de ce TP est de vous familiariser avec les notions d'URI, de comprendre en détail les échanges ainsi que le protocole HTTP et de réaliser vous-même des requêtes HTTP. Cette bonne connaissance de la mécanique HTTP vous permettra d'aborder sereinement la programmation Web proposée en B.U.T., côté serveur en PHP comme côté client en JavaScript.

Ce TP ne sera pas directement évalué, mais il vous est demandé de consigner vos réponses dans un dépôt Git qui vous sera utile lors de vos révisions.

Versionnage du projet

Pour ce sujet de TP, vous créerez un nouveau répertoire, vous initialiserez un dépôt Git dans ce répertoire et créerez un dépôt distant sur GitLab. Vous réaliserez une opération de validation avec git commit au moins une fois par question du sujet.

Initialisation du dépôt

  • Ouvrez un terminal puis utilisez la commande mkdir un_nom_de_répertoire pour créer un nouveau répertoire « protocole-http » dans « $HOME » suivie de la commande cd un_chemin_relatif_ou_absolu pour vous placer dans le répertoire
  • Initialisez le dépôt Git du projet
    git init
  • Effectuez une première validation
    git commit --allow-empty -m "Initial commit"
  • Éditez le fichier « .gitignore » pour exclure les fichiers binaires inutiles à votre projet (fichiers pptx du cours, …), les fichiers qui contiennent des mots de passe ou, dans le cas des projets collaboratifs, les fichiers créés par votre éditeur de texte (répertoire « .idea » pour PhpStorm)
  • Éditez un fichier « README.md » dans lequel doivent figurer :
    • un titre de niveau 1 contenant le titre explicite du projet
    • un titre de niveau 2 « Auteur(s) » vous permettant de préciser votre nom et votre prénom (ainsi que ceux de votre binôme, le cas échéant)
    • un titre de niveau 2 « Installation / Configuration » précisant les points essentiels permettant d'installer, de configurer et de lancer le projet
  • Ajoutez les fichiers au dépôt
    git add .
  • Effectuez une nouvelle validation
    git commit -m "Repository setup"
  • Si nécessaire, renommez la branche principale en « main » (une branche vide ne peut pas être renommée, c'est pourquoi ceci est fait après le premier commit)
    git branch -m main
    Notez que vous pouvez le faire de façon définitive avec la commande suivante, à condition d'utiliser git dans une version supérieure à 2.28
    git config --global init.defaultbranch main
  • Connectez-vous à l'application GitLab et créez un dépôt portant le même nom que votre nouveau répertoire en pensant à décocher la case « Initialize repository with a README »
  • Accordez la permission « Reporter » à votre enseignant de TP/TD
  • Associez le dépôt local et le dépôt distant
    git remote add origin https://iut-info.univ-reims.fr/gitlab/votre_login/protocole-http.git
  • Poussez le dépôt local vers le dépôt distant
    git push -u origin main

Consignes

  • Vous effectuerez une validation après chaque question.
  • À la fin de chaque séance, vous effectuerez une validation. Si cette validation contient du code incomplet ou ne fonctionnant pas, mentionnez-le dans le message de validation. Vous pousserez ensuite votre travail vers le dépôt distant.
  • Ce dépôt sera utilisé par votre enseignant(e) de TP pour évaluer votre travail, que cela conduise à un note ou pas. Assurez-vous donc régulièrement que tous les fichiers que vous souhaitez lui rendre sont bien présents dans le dépôt. Respectez les noms des fichiers qui vous sont demandés si des consignes particulières vous sont données.
  • Le dépôt lui-même sera évalué, soignez l'écriture de vos messages : clarté, pertinence, orthographe.

L'aide-mémoire Git et l'aide-mémoire GitLab de Monsieur Nourrit pourront vous être utiles.

Notion d'adresse Web

Les URI (Universal Ressource Identifier) sont un moyen d'identifier des ressources, comme le décrit la RFC 2396. Les URI sont une généralisation des URL (Universal Ressource Locator), permettant de localiser une ressource sous la forme de ce que nous appelons communément une adresse Web.

La structure des URI, dont la syntaxe dépend du protocole, est la suivante :

Le diagramme précédent est celui de la syntaxe d'une URI, son principe est repris en texte ci-après.

Le diagramme précédent peut être exprimé sous une forme texte dans laquelle les éléments entre crochets sont facultatifs :

scheme ":" ["//" authority] path ["?" query] ["#" fragment]
la partie authority, facultative, étant décomposée en :
[userinfo "@"] host [":" port]

Détaillons les divers éléments constitutifs des URI.

  • scheme représente le schéma de l'URI (protocole au sens large) :
    • http
    • https
    • ftp
    • news
    • mailto
    • file
    • tel
    Vous pouvez consulter la liste détaillée des schémas d'URI.
  • authority regroupe l'ensemble des informations nécessaires à la connexion :
    • userinfo qui est composé de username et password, séparés par « : » et suivis de « @ »
      • john@
      • john:easypassword@
    • host permet de désigner le nom DNS de l'hôte, son adresse IP v4 (sous la forme « A.B.C.D ») ou son adresse IP v6 (entre crochets « […] »)
      • intranet
      • iut-info.univ-reims.fr
      • www.imperial.ac.uk
      • example.com
      • 93.184.216.34
      • [2606:2800:220:1:248:1893:25c8:1946]
    • port, précédé de « : », vous permet de spécifier le port réseau
      • 80
      • 443
      • 22
      • 25565
  • path décrit le chemin de la ressource dans lequel les segments sont séparés par des « / » (slash)
    • /
    • /index.php
    • /users/cutrona/restricted/but/protocole-http/img/URI_syntax_diagram.svg
    Remarque importante

    Ce chemin ne désigne pas nécessairement un fichier stocké sur le serveur.

  • query est la « query string », c'est-à-dire la chaîne de requête, commençant par « ? », qui contient des données regroupées en un ensemble de couples « parameterName=encodedValue » séparés par « & »
    • ?a=12
    • ?action=logout
    • ?firstname=John&lastname=Doe
    • ?darkmode&theme=green (il n'y a pas nécessairement de valeur comme pour le paramètre darkmode)
    Remarque importante

    La partie query de l'URI correspond à des données qui vont implicitement passer du client au serveur interrogé.

    Les valeurs des paramètres doivent nécessairement être encodées pour que les caractères n'entrent pas en conflit avec ceux utilisés dans les URI (« # », « & », « : », …)

  • fragment (identificateur de fragment en français) désigne une ressource subordonnée de la ressource primaire, classiquement un élément identifié dans un document HTML
Travail à réaliser
  1. Trouvez la syntaxe des URI permettant :
    1. d'envoyer un mail (mais ne l'envoyez pas !) avec sujet du mail fourni (Ex : mail à jerome.cutrona@univ-reims.fr avec le sujet J'aime le Web)
    2. d'accéder à un répertoire partagé par un serveur ftp en anonyme (Ex : ftp.sunet.se ou ftp.proxad.net)
    3. d'accéder à un répertoire local sur votre poste de travail (Ex : /tmp sur Linux)
  2. Donnez les valeurs des éléments constitutifs des URI qui suivent :
    1. https://example.com/
    2. https://www.iut-rcc.fr/media-files/30677/but-info.pdf
    3. https://iut-info.univ-reims.fr/users/cutrona/intranet/installation-configuration/ubuntu-opennebula/index.html#objectifs-de-la-seance
    4. http://demo.ad-urca.univ-reims.fr/?info
    5. mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8&charset=utf8mb4
    6. https://www.univ-reims.fr/formation/catalogue-de-formation/but-informatique,23515,38949.html?args=R9qFsCnMmKDtxCa17YTDkHVqaqbfYRXwwTnCVt2witCDUIiVoUdkeMDp%2AXGEGm2SMIhvMbuZ3_kOrRxvJlk6dOorIryuNioRCyFFyPAvhl9tCdwYdtHRrwAvNC1tDg_H&formation_id=17#formationDetailDecriptions

Échanges HTTP

Le protocole HTTP (Hypertext Transfer Protocol) est un protocole d'échange client-serveur de la couche application. Il a été conçu dans les années 1990 pour répondre à la mise à disposition de ressources sur le World Wide Web. Ces ressources sont hébergées sur des serveurs HTTP et peuvent être récupérées et consultées à l'aide des URI.

Une interrogation HTTP classique se déroule toujours suivant ces étapes :

  1. Établissement d'une connexion TCP à la demande du client
  2. Échange HTTP :
    • Envoi d'une requête HTTP au serveur par le client
    • Traitement de la requête par le serveur
    • Envoi d'une réponse HTTP au client par le serveur
  3. Fermeture de la connexion TCP à l'initiative du serveur
  4. Interprétation par le client de la ressource récupérée

Établir la connexion avec le serveur nécessite évidemment de connaître son adresse IP v4 ou v6. Pour cela, si l'hôte est désigné par son FQDN (Fully qualified domain name), une phase de résolution DNS sera nécessaire.

La connexion réseau se fait classiquement sur le port 80 du serveur pour les URI « http:// » et sur le port 443 pour les URI « https:// ». Ces ports peuvent naturellement être modifiés dans la configuration du serveur pour des besoins spécifiques, comme la phase de développement d'une application Web. échange HTTP entre client et serveur

Ressources liées en HTTP 1.0

Lorsque la ressource récupérée est un contenu HTML, ce dernier est interprété par le navigateur afin de produire un rendu graphique pour l'utilisateur. Si ce contenu HTML fait référence à des feuilles de style, images, scripts JavaScript, le navigateur doit effectuer des nouvelles requêtes HTTP afin de récupérer ces ressources liées.

Dans le contexte de HTTP 1.0, le serveur ferme systématiquement la connexion réseau après avoir répondu au client. Ceci engendre des pertes de temps et de la consommation inutile de ressources pour établir de nouveau la connexion en cas de requêtes multiples sur le même serveur Web : multiples échanges HTTP entre client et serveur en HTTP 1.0

Ressources liées en HTTP 1.1 et plus

HTTP 1.1 introduit la possibilité de demander au serveur de ne pas mettre fin à la connexion réseau, et ainsi permettre d'effectuer plusieurs échanges HTTP sur la même connexion réseau pour gagner du temps et des ressources : multiples échanges HTTP entre client et serveur en HTTP 1.1 et +

Ce mécanisme est rendu possible par l'introduction de l'en-tête Connection sur lequel nous reviendrons lors de l'étude des requêtes HTTP.

Visualisation des échanges HTTP dans le navigateur

Les navigateurs Web intègrent une « barre de développement » qui apportent des outils précieux pour les développeurs Web. Cette « barre de développement » propose des outils similaires sur tous les navigateurs, avec toutefois quelques variations. Nous utiliserons systématiquement Firefox afin d'illustrer les outils et ne pas avoir à chercher la localisation ou l'option équivalente sur unn autre navigateur. Vous pourrez utiliser le navigateur de votre choix dans la suite de votre cursus.

Ressource principale

Observons les échanges relatés par la « barre de développement » lors de la récupération d'une ressource principale (presque) unique.

Travail à réaliser
  1. Si ce n'est pas déjà fait, lancez Firefox : Fenêtre du navigateur Firefox
  2. En appuyant sur F12 ou CTRL+SHIFT+I, vous activez la barre de développement : Fenêtre du navigateur Firefox avec la barre de développement active
  3. Activez l'onglet « Réseau » de la barre de développement : Fenêtre du navigateur Firefox avec la barre de développement active pour la partie réseau
  4. Saisissez l'adresse https://example.com Visualisation des échanges HTTP dans la barre de développement du navigateur
  5. Consultez la liste des ressources récupérées et répondez aux questions suivantes :
    1. Donnez le nom de la ressource principale
    2. Donnez la nature de la ressource principale
    3. Expliquez la présence de la ressource favicon.ico

Ressources liées

Observons les échanges relatés par la « barre de développement » lors de la récupération d'une ressource principale possédant des ressources liées.

Travail à réaliser
  1. Si ce n'est pas déjà fait, ouvrez le sujet de ce TP avec Firefox : sujet de TP affiché dans Firefox
  2. Ouvrez la « barre de développement » et constatez l'absence d'affichage d'échanges : visualisation des échanges HTTP dans la barre de développement du navigateur, absence d'échanges affichés
  3. Forcez le rechargement de la page Web avec SHIFT+F5 (sauf sur Firefox), SHIFT+CTRL+R ou le bouton « actualiser » en maintenant SHIFT visualisation des échanges HTTP dans la barre de développement du navigateur, échanges affichés
  4. En consultant la liste des ressources récupérées ainsi que leur contenu (vous pouvez consulter le code source de la page web et utiliser « l'inspecteur du style et du DOM » de Firefox), expliquez pourquoi les ressources suivantes sont demandées au serveur :
    1. « style.css »
    2. « correction.js »
    3. « URI_syntax_diagram.svg »
    4. « timer.png »

Messages HTTP

Jusqu'à présent, nous avons observé le dialogue entre le client et le serveur sans entrer dans le détail des messages échangés. La compréhension du contenu de ces messages permet de mieux comprendre le dialogue et poser des bases solides pour vos futurs développements Web. De manière générale, un dialogue HTTP consiste en l'échange d'un message HTTP de type requête envoyé par le client, auquel le serveur répond avec un message HTTP de type réponse à destination du client.

Les messages HTTP sont composés de texte structuré en lignes. Ceci signifie que chaque ligne a un sens particulier. La structure d'un message HTTP, de type requête comme de type réponse, est découpée ainsi :

  • Une ligne de requête (pour la requête) ou d'état (pour la réponse)
  • Plusieurs lignes d'en-tête facultatives
  • Une ligne sans aucun caractère (hormis le retour à la ligne)
  • Un corps de requête facultatif appelé charge utile (payload en anglais)

La structure globale est donc :

Requête ou état
En-tête: valeur d'en-tête
En-tête: valeur d'en-tête
En-tête: valeur d'en-tête
En-tête: valeur d'en-tête
En-tête: valeur d'en-tête
En-tête: valeur d'en-tête

contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP contenu de la charge utile du message HTTP 
Remarque importante

Le symbole «  » représente ici le « retour à la ligne », volontairement mis en évidence dans tout le message sauf la charge utile (payload).

Les messages, requête et réponse, peuvent être replacés dans la globalité de l'échange entre le client et le serveur : échanges HTTP entre client et serveur example.com

Requête HTTP

La première ligne de la requête HTTP est composée de 3 parties :

method path version
  • method (méthode ou verbe HTTP) est classiquement GET, POST ou HEAD (mais aussi PUT, DELETE ou PATCH pour les API Web) et correspond à l'opération que le client souhaite effectuer
  • path est l'URL de la ressource dont les éléments déductibles sont retirés en fonction du contexte, c'est-à-dire le protocole, l'hôte et port puisque la connexion est déjà établie
  • version est HTTP/1.0 ou HTTP/1.1 (HTTP/2 et HTTP/3 modifient le transport des données, mais pas la structure des messages)
  • GET / HTTP/1.0
  • POST /login HTTP/1.1
  • GET /register.php?firstname=John&lastname=Doe HTTP/1.1
  • HEAD /avatar.png HTTP/1.1

Cette première ligne peut être suivie d'informations relatives à la requête, les en-têtes HTTP :

  • en-tête général : concerne l'échange, la requête
    • Connection: close
    • Cache-Control: no-cache
  • en-tête de requête : précisions sur la requête ou le client
    • User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
    • Host: example.com
    • Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
    • Cookie: UserID=JohnDoe
  • en-tête d'entité : précisions sur les données envoyées dans le corps du message (payload)
    • Content-Length: 42
    • Content-Type: multipart/form-data; boundary=----WebKitFormBoundary37htlZnm5RVOvzxr

Le corps de la requête, utilisé en méthode POST, peut fournir :

  • la partie interrogative (la « query string »)
  • la partie interrogative et des fichiers à envoyer au serveur (méthode POST et contenu du corps multipart/form-data)
Remarque importante

Si la charge utile est non vide, l'en-tête Content-Type doit impérativement être présent pour que le serveur qui reçoit le contenu connaisse la nature de ce contenu afin de pouvoir l'interprêter correctement.

Le message HTTP qui suit est une requête envoyée l'hôte « example.com », utilisant la methode « GET » pour demander la ressource « / » :

GET / HTTP/1.1
Host: example.com
Connection: close
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pl;q=0.6
Cache-Control: no-cache
Connection: keep-alive
Pragma: no-cache
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36

Visualisation des requêtes HTTP

Maintenant que vous êtes conscient des échanges HTTP et de la structure des requêtes HTTP, vous allez observer des requêtes en fonction du navigateur et de la manière d'interroger le serveur. Pour cela, vous utiliserez, de manière directe ou indirecte, la ressource http://demo.ad-urca.univ-reims.fr/request/dump/ qui affiche la requête HTTP brute reçue par le serveur.

Travail à réaliser
  1. Visualisez la requête envoyée par Firefox en demandant l'adresse http://demo.ad-urca.univ-reims.fr/request/dump/.
  2. Observez la requête et expliquez tous ses éléments constitutifs
  3. Actualisez la page avec SHIFT+F5 (sauf sur Firefox), SHIFT+CTRL+R ou le bouton « actualiser » en maintenant SHIFT
  4. Observez et expliquez les changements dans la requête transmise au serveur
  5. Actualisez la page avec F5, CTRL+R ou le bouton « actualiser »
  6. Observez et expliquez les changements dans la requête transmise au serveur
  7. Activez l'onglet « Réseau » de la barre de développement
  8. Cochez la case « Désactiver le cache »
  9. Actualisez la page avec , CTRL+R ou le bouton « actualiser »
  10. Observez et expliquez les changements dans la requête transmise au serveur
  11. Décochez la case « Désactiver le cache »

Les précédentes observations ne concernent qu'une requête GET et sans « query string », c'est-à-dire sans paramètre. Vous allez maintenant tester divers cas de figure en utilisant comme point de départ la page Web http://demo.ad-urca.univ-reims.fr/request/.

Requête depuis un lien

Travail à réaliser
  1. Dans un nouvel onglet de Firefox, saisissez l'adresse http://demo.ad-urca.univ-reims.fr/request/ dans la barre d'adresse
  2. Ouvrez la « barre de développement »
  3. Cliquez sur le lien « Cliquez ici » de l'ensemble « …depuis un lien »
  4. Observez la requête, trouvez l'en-tête nouveau par rapport aux questions précédentes et expliquez son utilité

Requête depuis un formulaire en méthode GET

Travail à réaliser
  1. Revenez sur la page http://demo.ad-urca.univ-reims.fr/request/
  2. Observez le formulaire de l'ensemble « …depuis un formulaire en méthode GET » (visuel et code source HTML)
  3. Donnez l'endroit où est indiquée la méthode HTTP utilisée par ce formulaire
  4. Soumettez ce formulaire
  5. Cherchez les relations entre, d'un côté les champs et valeurs choisies dans le formulaire et, de l'autre côté la requête HTTP
  6. Revenez sur le formulaire et cliquez sur le bouton « ou ne pas soumettre »
  7. Cherchez les différences avec la précédente requête
  8. Revenez sur le formulaire et essayez diverses combinaisons de saisie (bouton radio coché ou pas) et observez l'impact sur la requête HTTP

Requête depuis un lien avec des paramètres

Travail à réaliser
  1. Revenez sur la page http://demo.ad-urca.univ-reims.fr/request/
  2. Cliquez sur le lien « Cliquez ici » de l'ensemble « …depuis un lien avec des paramètres »
  3. Cherchez les relations entre, d'un côté la requête HTTP de la question précédente et, de l'autre côté l'URL sur laquelle vous venez de cliquer et la requête HTTP que cela engendre

Requête depuis un formulaire en méthode POST

Travail à réaliser
  1. Revenez une nouvelle fois sur la page http://demo.ad-urca.univ-reims.fr/request/
  2. Observez le formulaire de l'ensemble « …depuis un formulaire en méthode POST » (visuel et code source HTML)
  3. Donnez l'endroit où est précisée méthode HTTP utilisée par ce formulaire
  4. Soumettez ce formulaire
  5. Expliquez la présence de l'entête de requête Content-Type
  6. Cherchez les relations entre, d'un côté les champs et valeurs choisies dans le formulaire et, de l'autre côté la requête HTTP
  7. Donnez les différences avec la même requête HTTP mais selon la méthode GET

Requête depuis un formulaire en méthode POST contenant un champ de type fichier

Travail à réaliser
  1. Revenez une dernière fois sur la page http://demo.ad-urca.univ-reims.fr/request/
  2. Observez le formulaire de l'ensemble « …depuis un formulaire en méthode POST contenant un champ fichier » (visuel et code source HTML)
  3. Trouvez une nouveauté concernant la balise <form>
  4. Trouvez le nouveau champ par rapport au précédent formulaire
  5. Soumettez ce formulaire sans avoir sélectionné de fichier
  6. Cherchez les relations entre, d'un côté les champs et valeurs choisies dans le formulaire et, de l'autre côté la requête HTTP
  7. Expliquez la présence de l'entête de requête Content-Type
  8. Expliquez la présence de boundary=… dans l'entête de requête Content-Type
  9. Expliquez la structure complexe de la charge utile de la requête
  10. Soumettez ce formulaire après avoir sélectionné un fichier de petite taille
  11. Cherchez les relations entre, d'un côté les champs et valeurs choisies dans le formulaire et, de l'autre côté la requête HTTP

Réponse HTTP

La première ligne de la réponse HTTP est composée de 3 parties :

"HTTP/"version status_code status_message
  • version vaut 1.0 ou 1.1 (HTTP/2 et HTTP/3 modifient le transport des données, mais pas la structure des messages)
  • status_code est le code d'état de la réponse sur 3 chiffres
  • status_message est le message typique associé au code précédent (n'importe quel message lisible par un humain peut être fourni)
  • HTTP/1.0 200 OK
  • HTTP/1.1 301 Moved Permanently
  • HTTP/1.1 404 Not Found
  • HTTP/1.1 500 Internal Server Error

Les codes d'état de réponse sont regroupés en fonction du premier chiffre :

  • 1xx : information
    • HTTP/1.1 100 Continue
  • 2xx : succès
    • HTTP/1.0 200 OK
    • HTTP/1.1 201 Created
  • 3xx : redirection
    • HTTP/1.1 301 Moved Permanently
    • HTTP/1.1 302 Found
    • HTTP/1.1 304 Not Modified
  • 4xx : erreur du client
    • HTTP/1.1 400 Bad Request
    • HTTP/1.1 403 Forbidden
    • HTTP/1.1 404 Not Found
    • HTTP/1.1 418 I'm a teapot
  • 5xx : erreur du serveur
    • HTTP/1.1 500 Internal Server Error
    • HTTP/1.1 501 Not Implemented
    • HTTP/1.1 503 Service Unavailable

La ligne de statut de la réponse est suivie, comme dans tout message HTTP, d'éventuels en-têtes, d'une ligne vide et possiblement d'un corps de réponse. Tout comme dans les requêtes HTTP, les en-têtes de réponse HTTP peuvent être regroupés en :

  • en-tête général : concerne l'échange, la requête
    • Connection: close
    • Cache-Control: no-cache
  • en-tête de réponse : précisions sur la réponse ou le serveur
    • Location: /login
    • Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/8.0.13
    • Set-Cookie: UserID=JohnDoe; Max-Age=3600
  • en-tête de l'entité : précisions sur les données envoyées dans le corps du message (payload)
    • Content-Length: 52
    • Content-Type: text/html; charset=utf-8
    • Content-Disposition: attachment; filename="bill.pdf"
    • Last-Modified: Mon, 24 Jan 2022 12:41:42 GMT

Le corps de la réponse, contient possiblement la ressource demandée par le client.

Remarque importante

Si la charge utile est non vide, l'en-tête Content-Type doit impérativement être présent pour que le client qui reçoit le contenu connaisse la nature de ce contenu afin de pouvoir l'interprêter correctement.

Suite à cette requête vue dans la partie précédente, le serveur a transmis cette réponse HTTP dont le corps (payload) a été tronqué :

HTTP/1.1 200 OK
Age: 243853
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Sat, 22 Jan 2022 18:05:22 GMT
Etag: "3147526947+ident"
Expires: Sat, 29 Jan 2022 18:05:22 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (bsa/EB15)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1256
Connection: close


<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
…
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>

Outil d'interrogation HTTP en ligne de commande

Habituellement, les agents utilisateurs (user agents) qui interrogent les sites Web sont les navigateurs Web, les robots d'indexation des moteurs de recherche ou encore les lecteurs d'écran ou les navigateurs en accessibility. Votre navigateur vous permet de :

  1. effectuer la connexion TCP sur l'adresse IP du serveur Web identifié dans l'URL saisie dans la barre d'adresse
  2. formuler la requête HTTP et de l'envoyer au serveur Web
  3. récupérer la réponse HTTP envoyée par le serveur Web
  4. décoder le contenu de la réponse HTTP pour en faire un rendu graphique

L'objectif étant ici d'étudier le protocole, les échanges et les messages HTTP, vous allez utiliser un outil en ligne de commande qui permet de :

  1. effectuer la connexion TCP sur l'adresse IP du serveur Web dont le nom est fourni en paramètre de la ligne de commande
  2. envoyer au serveur Web la requête HTTP que vous aurez formulée dans un fichier désigné en paramètre de la ligne de commande
  3. récupérer la réponse HTTP envoyée par le serveur Web
  4. afficher dans le terminal le contenu brut de la réponse HTTP

Cet outil en ligne de commande, écrit en PHP et développé en interne, s'utilise de la façon suivante :

http [--secure] --host host --port port file
  • --secure est une option facultative pour effectuer une connexion sécurisée sur le serveur (pour HTTPS)
  • --host host permet de donner le nom ou l'adresse IP du serveur sur lequel vous souhaitez vous connecter
  • --port port permet de donner le port du serveur sur lequel vous souhaitez vous connecter
  • file correspond au nom du fichier contenant la requête HTTP complète que vous souhaitez soumettre au serveur

Mise en place de l'outil

Afin de pouvoir utiliser l'outil quel que soit votre répertoire de travail, vous allez placer le script dans un répertoire bin à la racine de votre compte et ajouter ce chemin à la variable d'environnement PATH. Cette démarche est très classique et sera réutilisée dans d'autres TP tout au long de votre formation.

Travail à réaliser
  1. Ouvrez un terminal
  2. S'il n'existe pas, créez un répertoire bin dans votre répertoire d'accueil :
    mkdir ~/bin
  3. Placez-vous dans le répertoire bin votre répertoire d'accueil :
    cd ~/bin
  4. Si vous ne l'avez pas déjà fait, ajoutez le répertoire ~/bin à la variable PATH en modifiant le fichier ~/.bashrc pour y insérer la ligne suivante :
    export PATH="$HOME/bin:$PATH"
  5. Si vous avez modifié le script shell ~/.bashrc, rechargez-le dans votre environnement en passant la commande :
    source ~/.bashrc
  6. Vérifiez la présence du chemin correspondant à ~/bin dans la variable PATH en passant la commande :
    echo $PATH
  7. Récupérez le script de l'outil d'interrogation HTTP en utilisant « enregistrer sous »
  8. Placez le script dans le répertoire ~/bin
  9. Rendez le script exécutable à l'aide de setfacl :
    setfacl -m u::rwx ~/bin/http
  10. Placez-vous dans le répertoire de votre projet :
    cd chemin_relatif_ou_absolu/protocole-http
  11. Vérifiez le bon fonctionnement en passant la commande :
    http
    qui devrait produire cette sortie :
    USAGE:
    http --host|-h host --port|-p port [--secure|-s] file
    ERROR: missing parameters
    

Première utilisation de l'outil

À titre d'exemple, vous allez interroger le site http://example.com.

Remarque importante

Tous les fichiers contenant des requêtes HTTP seront placés dans un répertoire requests que vous créerez dans votre projet versionné.

Travail à réaliser
  1. Créez un répertoire requests dans votre projet
  2. Récupérez le fichier example.com-get-root.txt en utilisant « enregistrer sous »
  3. Placez le fichier dans le répertoire requests de votre projet
  4. Consultez le contenu de ce fichier
  5. Lancez la commande
    http --host example.com --port 80 requests/example.com-get-root.txt
  6. Observez l'affichage produit par cette commande :
    REQUEST:
    1: GET / HTTP/1.1
    2: Host: example.com
    3: Connection: close
    4: 
    
    --------------------------------------------------------------------------------
    RESPONSE:
    HTTP/1.1 200 OK
    Age: 508025
    Cache-Control: max-age=604800
    Content-Type: text/html; charset=UTF-8
    Date: Tue, 18 Jan 2022 22:08:16 GMT
    Etag: "3147526947+ident"
    Expires: Tue, 25 Jan 2022 22:08:16 GMT
    Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
    Server: ECS (bsa/EB11)
    Vary: Accept-Encoding
    X-Cache: HIT
    Content-Length: 1256
    Connection: close
    
    <!doctype html>
    <html>
    <head>
        <title>Example Domain</title>
    
        <meta charset="utf-8" />
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <style type="text/css">
        body {
            background-color: #f0f0f2;
            margin: 0;
            padding: 0;
            font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
            
        }
        div {
            width: 600px;
            margin: 5em auto;
            padding: 2em;
            background-color: #fdfdff;
            border-radius: 0.5em;
            box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
        }
        a:link, a:visited {
            color: #38488f;
            text-decoration: none;
        }
        @media (max-width: 700px) {
            div {
                margin: 0 auto;
                width: auto;
            }
        }
        </style>    
    </head>
    
    <body>
    <div>
        <h1>Example Domain</h1>
        <p>This domain is for use in illustrative examples in documents. You may use this
        domain in literature without prior coordination or asking for permission.</p>
        <p><a href="https://www.iana.org/domains/example">More information...</a></p>
    </div>
    </body>
    </html>
    connection closed
    
  7. Repérez la requête et la réponse dans l'affichage
  8. Distinguez les 4 parties de la requête
  9. Distinguez les 4 parties de la réponse
  10. Effectuez la même requête en utilisant HTTPS
    Information

    Les services réseau HTTP et HTTPS sont différents, ils sont donc fournis par le serveur sur des ports différents.

  11. Déterminez à quoi correspondent les en-têtes de réponse suivants ainsi que la signification des valeurs qui leur sont associées :
    • Content-Type
    • Last-Modified
    • Content-Length

Quand un serveur Web est plusieurs serveurs Web

Principe en HTTP 1.0

La version 1.0 du protocole HTTP permet d'envoyer une requête au serveur Web sur lequel le client est connecté en TCP sur le port 80. L'adresse IP du serveur est déterminée par le client grâce à une résolution DNS avant de tenter la connexion. Ce mécanisme implique que ce serveur Web est unique : échanges HTTP entre client et serveur example.com désigné par example.com dans le navigateur

La résolution DNS et la connexion au serveur reviennent donc à n'utiliser que l'adresse IP du serveur sur le client : échanges HTTP entre client et serveur example.com désigné par son adresse IP 93.184.216.34 dans le navigateur

Principe en HTTP 1.1

La version 1.1 du protocole permet d'héberger plusieurs serveurs Web sur le même serveur Web. Cette proposition semble irréalisable, mais elle est rendue possible par l'introduction d'un en-tête Host qui permet de préciser, dans la requête HTTP, l'hôte auquel le message de requête est destiné. Ce principe sous-entend que l'hôte (le serveur possédant une adresse IP) hébergeant le serveur Web peut héberger d'autres serveurs Web sur la même adresse IP et sur le même port réseau.

Étudions dans un premier temps les relations entre nom DNS et adresse IP (ces manipulations fonctionnent uniquement dans le réseau du département informatique ou dans son VPN) :

Travail à réaliser
  1. Ouvrez un terminal
  2. Déterminez l'adresse IP de mon serveur Web dont le nom DNS est cutrona à l'aide de la commande host :
    host cutrona
    cutrona.ad-urca.univ-reims.fr is an alias for cutron01.ad-urca.univ-reims.fr.
    cutron01.ad-urca.univ-reims.fr is an alias for web-prod.ad-urca.univ-reims.fr.
    web-prod.ad-urca.univ-reims.fr is an alias for node016.ad-urca.univ-reims.fr.
    node016.ad-urca.univ-reims.fr has address 10.31.6.118
  3. Constatez que cutrona est en réalité cutrona.ad-urca.univ-reims.fr car les machines du département informatique sont dans le domaine DNS ad-urca.univ-reims.fr
  4. Constatez les divers alias DNS et l'adresse IP associée à cutrona
  5. Déterminez l'adresse IP du serveur Web de M. Arganini dont le nom DNS est arganini
  6. Déterminez l'adresse IP du serveur Web de M. Jonquet dont le nom DNS est jonquet
  7. Déterminez l'adresse IP du serveur Web de votre propre serveur Web dont le nom DNS est votre_login
  8. Utilisez votre navigateur pour interroger, directement avec son adresse IP v4, le serveur Web dont vous venez de déterminer l'adresse IP v4

Vous venez de constater que les ressources Web de tous les enseignants et étudiants du département informatique sont portées par le même serveur dont l'adresse IP v4 est 10.31.6.118. Dans ces conditions, une fois votre navigateur connecté sur le port 80 de 10.31.6.118, une requête HTTP demandant la ressource « / » est nécessairement indéterminée puisque le serveur possède autant de ressources « / » que de serveurs d'hébergement Web virtuel. Il est donc impératif que la requête contienne le nom DNS du serveur d'hébergement Web virtuel qui doit être réellement sollicité. C'est le but de l'en-tête Host.

Interrogation HTTP en ligne de commande

Afin de vous rendre compte des échanges de messages HTTP, vous allez utiliser l'outil d'interrogation HTTP en ligne de commande vu plus tôt pour effectuer diverses requêtes HTTP et prendre connaissance des réponses HTTP fournies par le serveur interrogé.

Remarque importante

Dans une requête HTTP, vous aurez sans nul doute noté l'importance de la ligne contenant uniquement un retour à la ligne qui marque la fin des en-têtes. Afin de prendre conscience de la présence ou non de cette ligne fondamentale dans vos requêtes, vous devriez systématiquement afficher les numéros de lignes dans votre éditeur de texte.

Requête HTTP 1.0 sur le serveur 10.31.6.118

Travail à réaliser
  1. Écrivez dans le fichier requests/10.31.6.118-get-http10.txt la requête HTTP 1.0 demandant la ressource « / » au serveur 10.31.6.118
  2. Soumettez la requête au serveur
  3. Donnez le code d'état de la réponse HTTP
  4. Lisez le code HTML contenu dans la charge utile de la réponse HTTP pour comprendre le sens de ce code d'état
  5. Donnez le type et la version du serveur Web
  6. Donnez le système d'exploitation annoncé par le serveur

Requête HTTP 1.0 sur le serveur cutrona

Travail à réaliser
  1. Effectuez la requête requests/10.31.6.118-get-http10.txt en vous connectant sur l'hôte cutrona
  2. Donnez les différences avec la précédente requête

Requête HTTP 1.1 sur le serveur 10.31.6.118

Travail à réaliser
  1. Écrivez dans le fichier requests/10.31.6.118-get-http11.txt la requête HTTP 1.1 demandant la ressource « / » au serveur 10.31.6.118
  2. Soumettez la requête au serveur
  3. Donnez le code d'état de la réponse HTTP
  4. Précisez à quoi correspondent les dernières lignes dans l'affichage de la commande :
    waiting...
    waiting...
    waiting...
    waiting...
    waiting...
    connection closed
    
  5. Modifiez la requête HTTP dans un nouveau fichier requests/10.31.6.118-get-http11-connection-close.txt afin que le serveur n'attende plus avant de couper la connexion
  6. Effectuez la nouvelle requête requests/10.31.6.118-get-http11-connection-close.txt en vous connectant sur l'hôte 10.31.6.118
  7. Constatez la présence d'un nouvel en-tête dans lé réponse du serveur
    Remarque importante

    Puisque l'outil d'interrogation HTTP en ligne de commande est prévu pour n'effectuer qu'une seule requête, vous utiliserez à présent systématiquement l'en-tête Connection: close dans vos requêtes.

  8. Utilisez votre navigateur pour accéder au serveur Web 10.31.6.118
  9. Observez les échanges réseau entre votre navigateur et le serveur Web
  10. Expliquez la présence de ressources liées à la ressource principale

Requête HTTP 1.1 sur le serveur demo.ad-urca.univ-reims.fr

Travail à réaliser
  1. Écrivez dans le fichier requests/demo-get-bonjour.html.txt la requête HTTP demandant la ressource « http://demo.ad-urca.univ-reims.fr/bonjour.html »
  2. Soumettez la requête au serveur
  3. Écrivez dans le fichier requests/demo-post-bonjour.html.txt la requête HTTP demandant la ressource « http://demo.ad-urca.univ-reims.fr/bonjour.html » selon la méthode POST
  4. Soumettez la requête au serveur
  5. Observez les deux réponses précédentes du serveur pour distinguer des similitudes et/ou des différences
  6. Écrivez dans le fichier requests/demo-get-query-string-bip-nb.txt la requête HTTP demandant la ressource « http://demo.ad-urca.univ-reims.fr/query-string/ » selon la méthode GET et en passant les paramètres de requête « bip » valant « meuh, meuh & meuh » ainsi que « nb » valant « 12 »
  7. Soumettez la requête au serveur
  8. Écrivez dans le fichier requests/demo-post-query-string-bip-nb.txt la requête HTTP demandant la ressource « http://demo.ad-urca.univ-reims.fr/query-string/ » selon la méthode POST et en passant les paramètres de requête « bip » valant « meuh, meuh & meuh » ainsi que « nb » valant « 12 »
  9. Soumettez la requête au serveur
  10. Distinguer des similitudes et/ou des différences entre la requête faite avec la méthode GET et celle faite avec la méthode POST

Requête HTTP et gestion du cache

Travail à réaliser
  1. Lisez la documentation des cas d'utilisation des requêtes conditionnelles en ne tenant pas compte de l'en-tête ETag que nous n'utiliserons pas.
  2. Ouvrez de nouveau la requête HTTP requests/demo-get-bonjour.html.txt demandant la ressource « http://demo.ad-urca.univ-reims.fr/bonjour.html »
  3. Soumettez la requête au serveur
  4. Cherchez l'en-tête donnant la date de dernière modification de la ressource
  5. Écrivez dans le fichier requests/demo-get-bonjour.html-if-modified-since.txt la requête HTTP demandant la ressource « http://demo.ad-urca.univ-reims.fr/bonjour.html » uniquement si elle est modifiée depuis une date postérieure à celle constatée dans la question précédente
  6. Soumettez la requête au serveur
  7. Donnez le code d'état de la réponse HTTP (ce ne doit pas être 200 !)

Cookies et sessions

Le protocole HTTP est un protocole sans état, ce qui signifie que le serveur ne conserve aucune information sur un client et n'a même aucune conscience de répondre au même client. Ceci est dû au fait que la mission du serveur est de donner une réponse à une requête, sans vision de la globalité des échanges. Dans ces conditions, il est impossible d'entrevoir la réalisation d'une application Web qui nécessite d'apporter une réponse particulière à chaque client. Heureusement, le protocole HTTP prévoit que le serveur puisse demander à un client particulier de stocker une information qu'il devra retransmettre au serveur en cas de nouvelle requête. Cette information est un cookie.

Cookies

Le premier mécanisme permettant de produire des réponses spécifiques pour un client est celui des cookies. Le serveur décide de donner la responsabilité au client de lui rappeler un ensemble de valeurs. Le client qui les reçoit doit donc les retransmettre à chaque nouvelle requête sur le même serveur. échanges HTTP entre client et serveur avec gestion des cookies sur le client

Travail à réaliser
  1. Accédez à http://demo.ad-urca.univ-reims.fr/cookie/ avec Firefox
  2. Ouvrez la barre de développement
  3. Cherchez des traces de cookies dans la requête et la réponse HTTP dans l'onglet « Réseau »
  4. Observez l'absence de cookies dans l'onglet « Stockage » (« Application » pour Chrome)
  5. Cliquez sur le lien pour choisir le thème « dark » ou « gray »
  6. Cherchez des traces de cookies dans la requête et la réponse HTTP dans l'onglet « Réseau »
  7. Observez les cookies dans l'onglet « Stockage » (« Application » pour Chrome)
  8. Donnez la durée de validité du cookie
  9. Cliquez sur le lien « Retour à l'accueil »
  10. Cherchez des traces de cookies dans la requête et la réponse HTTP dans l'onglet « Réseau »
  11. Actualisez la page Web
  12. Cherchez des traces de cookies dans la requête et la réponse HTTP dans l'onglet « Réseau »
  13. Fermez votre navigateur
  14. Accédez à http://demo.ad-urca.univ-reims.fr/cookie/ avec Firefox
  15. Expliquez le maintien du thème, même après fermeture du navigateur
  16. Cliquez sur le lien pour choisir un autre thème
  17. Cherchez des traces de cookies dans la requête et la réponse HTTP dans l'onglet « Réseau »
  18. Observez les cookies dans l'onglet « Stockage » (« Application » pour Chrome)

Vous connaissez à présent le fonctionnement d'un cookie, vous allez tenter de mesurer les conséquences de sa modification non contrôlée par le client.

Travail à réaliser
  1. Accédez à http://demo.ad-urca.univ-reims.fr/cookie/ avec Firefox
  2. Ouvrez la barre de développement
  3. Observez les cookies dans l'onglet « Stockage »
  4. Éditez la valeur du cookie en effectuant un double clic dessus
  5. Donnez successivement la valeur light, gray ou dark au cookie
  6. Validez la nouvelle valeur en appuyant sur ENTER
    Remarque importante

    Comme vous venez de le voir, les manipulations de cookie sont facilement accessibles dans la barre de développement de Firefox. Si vous utilisez Chrome, vous devrez exécuter le code JavaScript document.cookie='nom_cookie=valeur_cookie' dans la console JavaScript de la barre de développement pour fixer la valeur « valeur_cookie » du cookie « nom_cookie »..

  7. Actualisez la page Web
  8. Constatez le changement de thème
  9. Cherchez des traces de cookies dans la requête et la réponse HTTP dans l'onglet « Réseau » de la barre de développement
  10. Donnez à présent une valeur différente de light, gray ou dark au cookie
  11. Actualisez la page Web
  12. Constatez le changement de thème
  13. Cherchez des traces de cookies dans la requête et la réponse HTTP dans l'onglet « Réseau » de la barre de développement
  14. Affichez le code source HTML de la page Web
  15. Cherchez les erreurs dans le code source HTML de la page Web
  16. Imaginez le fonctionnement interne du site ayant entrainé ces erreurs

Sessions

Les cookies ont une utilité limitée quand il s'agit de mémoriser des informations volumineuses ou sensibles puisqu'elles sont stockées sur le client et que ce dernier transmet les valeurs à chaque nouvelle requête sur le serveur concerné. Vous avez découvert les sessions en cours magistral et leur capacité à stocker sur le serveur une grande quantité de données, sensibles ou non, dont le lien avec un client particulier est maintenu par un cookie de session qui identifie ledit client.

Principe

Le principe du cookie vu précédemment reste valide et des données de session sont associés au client identifié par le cookie : échanges HTTP entre client et serveur avec gestion des sessions sur le serveur

Travail à réaliser
  1. Ouvrez un nouvel onglet dans Firefox
  2. Activez l'onglet « Réseau » de la barre de développement
  3. Accédez à http://demo.ad-urca.univ-reims.fr/session/ dans cet onglet
  4. Observez la réponse HTTP
  5. Donnez la durée de vie du cookie déposé par le serveur
  6. Mémorisez les 4 derniers caractères de la valeur du cookie de session PHPSESSID
  7. Identifiez-vous avec vos identifiants URCA
  8. Consultez votre « profil » sur ce site
  9. Fermez toutes les fenêtres de Firefox
  10. Relancez Firefox sur http://demo.ad-urca.univ-reims.fr/session/
  11. Constatez que vous n'êtes plus identifié
  12. Vérifiez si la valeur du cookie de session PHPSESSID a changé
  13. Déterminez à quoi correspond la durée de vie « Session » du cookie
  14. Identifiez-vous avec vos identifiants URCA
  15. Accédez à l'onglet « Stockage » de la barre de développement
  16. Mémorisez les 4 derniers caractères de la valeur du cookie de session PHPSESSID
  17. Supprimez le cookie de session PHPSESSID
  18. Rechargez la page
  19. Constatez que vous n'êtes plus identifié
  20. Accédez à l'onglet « Stockage » de la barre de développement
  21. Vérifiez si la valeur du cookie de session PHPSESSID a changé
  22. Identifiez-vous avec vos identifiants URCA
  23. Vérifiez si la valeur du cookie de session PHPSESSID a changé

Le cookie de session faisant le lien entre le client et ses données de session sur le serveur, vous allez volontairement réutiliser le cookie dans un second navigateur et constater l'accès simultané à la session.

Travail à réaliser
  1. Dans Firefox :
    1. Utilisez le bouton « Se déconnecter » sur le site http://demo.ad-urca.univ-reims.fr/session/
    2. Vérifiez que vous êtes bien déconnecté de votre compte sur le site
  2. Dans Chrome :
    1. Ouvrez un nouvel onglet
    2. Accédez à http://demo.ad-urca.univ-reims.fr/session/
    3. Identifiez-vous avec vos identifiants URCA
    4. Accédez à l'onglet « Application » de la barre de développement
    5. Copiez le la valeur du cookie de session PHPSESSID
  3. Dans Firefox :
    1. Activez l'onglet « Stockage » de la barre de développement
    2. Modifiez la valeur du cookie de session PHPSESSID pour lui donner celle copiée depuis Chrome
    3. Rechargez la page
    4. Constatez que vous êtes identifié
    5. Consultez le profil pour vous assurer de la présence des informations personnelles
    6. Déconnectez-vous du site
  4. Dans Chrome :
    1. Rechargez la page
    2. Constatez que vous n'êtes plus identifié
    3. Identifiez-vous de nouveau avec vos identifiants URCA
  5. Dans Firefox :
    1. Rechargez la page
    2. Constatez que vous êtes également identifié
  6. Dans Chrome :
    1. Accédez à l'onglet « Application » de la barre de développement
    2. Supprimez le cookie de PHPSESSID
    3. Constatez que vous n'êtes plus identifié
  7. Dans Firefox :
    1. Constatez que vous êtes toujours identifié

Toute la sécurité de l'accès aux données par le client repose sur le cookie de session, vous venez de le constater en le partageant délibérément entre vos deux navigateurs. Voyons comment un site mal conçu pour laisser s'échapper cette donnée cruciale.

La faille de sécurité repose sur le « Cross-Site Scripting (XSS) ». Vous allez vous faire dérober votre cookie de session du site http://demo.ad-urca.univ-reims.fr/session/ qui sera transmis et stocké sur le site pirate http://hacker.ad-urca.univ-reims.fr/. Le piège est un simple lien hypertexte envoyé par mail ou placé sur un site malveillant. Le site http://demo.ad-urca.univ-reims.fr/session/ comporte la faille de sécurité classique de réflexion : le site web insère, sans aucun contrôle ni modification, une donnée reçue dans la requête HTTP d'un client. Si la donnée reçue est un texte contenant <script>…</script> et que ce texte est inséré dans le code HTML de la réponse HTTP, le script JavaScript sera exécuté par le navigateur. Et si cette donnée est transmise selon la méthode HTTP GET, il est facile de construire un lien piégé.

Le diagramme qui suit récapitule les étapes d'identification de l'utilisateur suivies du vol du cookie. échanges HTTP entre client et serveur avec gestion des sessions sur le serveur ainsi que l'échange avec un voleur de cookie

À vous de vous faire voler votre cookie de session !

Travail à réaliser
  1. Formez un groupe de deux personnes : vous jouerez chacun le rôle la victime puis chacun le rôle du hacker en consultant les données personnelles de l'autre
  2. Victime, dans Chrome :
    1. Accédez à http://demo.ad-urca.univ-reims.fr/session/, le site cible de l'attaque
    2. Identifiez-vous avec vos identifiants URCA
    3. Accédez à l'onglet « Application » de la barre de développement
    4. Mémorisez les 4 derniers caractères de la valeur du cookie de session PHPSESSID
    5. Copiez le lien du sujet de TP (c'est le sujet de TP qui contient le lien piégé)
    6. Ouvrez un nouvel onglet dans Chrome
    7. Accédez à l'onglet « Réseau » de la barre de développement pour ce nouvel onglet
    8. Collez le lien du sujet de TP dans ce nouvel onglet
    9. Cliquez sur le lien piégé suivant dans le nouvel onglet dans Chrome pour voir le résultat piégé de recherche de « licorne » sur le site cible de l'attaque http://demo.ad-urca.univ-reims.fr/ et vous faire voler votre cookie de session au passage ! En cliquant sur ce lien, vous avez transmis un paramètre de requête contenant du code JavaScript qui a été inséré dans la page Web produite par le serveur sans aucune vérification
    10. Observez l'URL sur laquelle vous venez de cliquer
    11. Donnez la valeur de la « query string »
    12. Décodez la valeur de query contenue dans la « query string »
    13. Donnez la nature du texte décodé
    14. Expliquez le fonctionnement du texte décodé
    15. Affichez le code HTML source du résultat piégé de recherche de « licorne »
    16. Constatez la présence du texte correspondant à la valeur de query dans le code source HTML (et c'est là que réside l'erreur commise par le code PHP côté serveur !)
    17. Observez les requêtes réseau nécessaires à l'affichage du résultat piégé de recherche de « licorne »
    18. Constatez le chargement d'une ressource externe au site ciblé par l'attaque
    19. Rendez-vous sur http://hacker.ad-urca.univ-reims.fr/
    20. Constatez la présence de votre cookie de session dans la base de données du site pirate
  3. Exploitation du cookie volé par le hacker, dans Firefox :
    1. Rendez-vous sur http://hacker.ad-urca.univ-reims.fr/
    2. Copiez la valeur du cookie de session de la personne avec laquelle vous travaillez (le site http://hacker.ad-urca.univ-reims.fr/ collecte les cookies de tous les groupes de TP, les 50 vols les plus récents sont affichés)
    3. Accédez à http://demo.ad-urca.univ-reims.fr/session/, le site cible de l'attaque
    4. Vérifiez que vous n'êtes PAS identifié avec votre compte personnel et déconnectez-vous si nécessaire
    5. Accédez à l'onglet « Stockage » de la barre de développement de Firefox
    6. Modifiez le cookie de session pour lui donner la valeur du cookie volé
      Remarque importante

      Les manipulations de cookie sont facilement accessibles dans la barre de développement de Firefox. Si vous utilisez Chrome, vous devrez exécuter le code JavaScript document.cookie='nom_cookie=valeur_cookie' dans la console JavaScript de la barre de développement pour fixer la valeur « valeur_cookie » du cookie « nom_cookie ».

    7. Rechargez la page
    8. Constatez que vous êtes identifiés sous le nom de l'autre personne
    9. Cliquez sur le lien « Voir le profil »
    10. Constatez que vous pouvez naviguer avec l'identité de l'autre personne et accédez à ses informations

Échanges HTTP et PHP en mode serveur

Maintenant que vous maîtrisez le protocole HTTP, observons le détail des échanges lorsque la ressource demandée par le client se termine par « .php » : échanges HTTP entre client et serveur comprenant un module PHP

Dans ce contexte, le but de PHP est de produire la réponse HTTP. Dans une version simple, lorsque le navigateur interroge le serveur pour la ressource « /hello.php », le serveur va demander au module PHP d'exécuter le code PHP contenu dans hello.php. Ce code PHP peut alors exécuter toutes les instructions souhaitées par le développeur et produire la charge utile à l'aide de echo. La réponse HTTP complète (ligne d'état de la réponse, en-têtes, ligne vide et charge utile) est construite par le moteur PHP sans intervention du développeur puis transmise au navigateur ayant envoyé la requête. Dans une version plus complexe, le développeur du code PHP peut intervenir sur l'état de la réponse HTTP à l'aide de la fonction PHP http_response_code(), modifier ou fixer des en-têtes avec la fonction PHP header(), placer des cookies avec la fonction PHP setcookie() et produire la charge utile à l'aide de echo.