Les cookies
Ce nouveau tutoriel introduit le mécanisme des cookies. Nous définirons ensemble ce qu'est un cookie et à quoi il sert. Puis nous aborderons les principes de sécurité relatifs aux cookies. Ensuite nous apprendrons à générer et lire le contenu d'un cookie. Nous terminerons ce tutoriel sur la suppression du cookie, le stockage des valeurs d'un type complexe par sérialisation / désérialisation avant de conclure sur les cas d'utilisation les plus fréquents.
Qu'est-ce qu'un cookie ?
Le mécanisme des cookies a été inventé par la société Netscape dans le but de palier à certaines faiblesses du protocole HTTP mais aussi d'étendre les possibilités de relation entre le client et le site web. Leur fonction est le stockage, pendant une période donnée, d'une information relative à l'utilisateur (son pseudo, sa date de dernière connexion, son âge, ses préfèrences...).
En pratique, les cookies sont de simples fichiers textes ne pouvant excéder 4Ko. Ils sont stockés sur le disque dur de l'internaute et gérés par les navigateurs (Firefox, Internet Explorer, Safari, Opéra, AvantBrowser...). Leur acceptation est soumise aux filtres des navigateurs. En effet, ces derniers sont capables de refuser des cookies. Leur utilisation doit donc être scrupulesement réfléchie.
Pour des raisons de sécurité, des "normes" ont fixé à 20 le nombre maximal de cookies envoyés pour un même domaine.
Qu'en est-il de la sécurité ?
Il y'a encore quelques années les cookies faisaient peur. Certains profanes se persuadaient qu'ils étaient dangereux, qu'ils pouvaient exécuter des programmes malicieux sur leur ordinateur ou bien récupérer des informations personnelles ou confidentielles. Or ce n'est pas le cas. Un cookie n'est ni plus ni moins qu'un fichier texte de très petite taille. Il ne peut donc ni être exécuté ni même lancer des programmes à lui seul. Il ne sert uniquement à stocker une information en vue d'une réutilisation ultérieure. En revanche, rien n'empêche un programme pirate d'être exécuté par l'utilisateur (mais à son insu) qui va récupérer des informations confidentielles ou personnelles, puis les stocker dans un cookie qu'il crée et envoie au serveur Web. Ce dernier se chargera de récupérer les informations transmises et de les utiliser contre l'utilisateur.
La création d'un cookie demande néanmoins le respect de quelques règles de sécurité et de bon sens. Le cookie étant stocké sur le disque dur du client, son accès n'y est donc pas sécurisé. Un cookie pourra être lu, modifié ou supprimé sans difficulté par un utilisateur malintentionné. Il est donc fortement déconseillé de stocker des informations sensibles comme :
- des informations confidentielles à l'intérieur (mot de passe par exemple).
- des identifiants de connexion facilement identifiables comme un login.
Un cookie devrait généralement ne servir qu'à des fins statistiques, de personnalisation d'affichage ou bien à la multi pagination de formulaires. Et encore dans ce dernier cas, la meilleure solution serait d'avoir recours au mécanisme des sessions.
Génération d'un cookie avec setcookie()
La création d'un cookie repose sur l'envoi d'entêtes HTTP au navigateur du client au moyen de la fonction setcookie(). Cela sous-entend donc qu'il faudra l'appeller avant tout envoi de données au navigateur (print(), echo(), tag html, espace blanc...) sous peine de générer une erreur de type « Warning : Cannot send session cookie - headers already sent by... ».
La fonction setcookie() peut prendre jusqu'à 7 paramètres. Seul le premier est obligatoire car il définit le nom du cookie. Elle renvoie un booléen : true en cas de succès et false si échec.
Signature de la fonction setcookie()bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure [, bool httponly]]]]]] )
Le tableau ci-dessous récapitule les valeurs que peuvent prendre chacun de ces paramètres.
Paramètre | Explications | ||||
---|---|---|---|---|---|
Les paramètres de la fonction setcookie() | |||||
name | Nom du cookie | ||||
value | Valeur du cookie | ||||
expire | Date d'expiration du cookie au format timestamp UNIX, c'est à dire un nombre de secondes écoulées depuis le 01 janvier 1970 | ||||
path | Chemin sur le serveur dans lequel le cookie sera valide. Si la valeur '/' est spécifiée alors le cookie sera visible sur tout le domaine. Si '/examples/' est précisé alors le cookie sera visible dans le répertoire /examples/ et tous ses sous-dossiers | ||||
domain | Domaine sur lequel le cookie sera valable. Si la valeur est '.domaine.com' alors le cookie sera disponible sur tout le domaine (sous-domaines compris). Si la valeur est 'www.domaine.com' alors le cookie ne sera valable que dans le sous-domaine 'www' | ||||
secure | Ce paramètre prend pour valeur un booléen qui définit si le cookie doit être utilisé dans un contexte de connexion sécurisée par protocole HTTPS | ||||
httponly | Ce paramètre prend pour valeur un booléen qui définit si le cookie sera accessible uniquement par le protocole HTTP. Cela signifie que le cookie ne sera pas accessible via des langages de scripts, comme Javascript. Cette configuration permet de limiter les attaques via XSS (bien qu'elle ne soit pas supportée par tous les navigateurs). Ajouté en PHP 5.2.0 |
Le code suivant illustre la création d'un cookie caractérisé par un nom, une valeur et une date de validité d'un mois. Il simule l'enregistrement du design d'un site que l'utilisateur préfère. Grâce à ce cookie, le site sera affiché avec ce thème graphique automatiquement à la prochaine visite de l'internaute.
Création d'un cookie<?php// Création du cookie?>
Remarques :
[1] Lorsqu'un cookie est créé depuis une page, il ne devient disponible qu'à partir de la page suivante car il faut que le navigateur envoit le cookie au serveur.
[2] Un cookie dont la date d'expiration n'est pas précisée est enregistré dans la mémoire vive de l'ordinateur et non sur le disque dur. Il sera effacé à la fermeture du navigateur.
Lecture d'un cookie
Lorsqu'un internaute interroge un site web repéré par un nom de domaine, son navigateur envoie au serveur la liste des cookies disponibles pour ce domaine. PHP les réceptionne puis construit un tableau associatif superglobal nommé $_COOKIE. Les clés correspondent aux noms des cookies et les valeurs aux valeurs inscrites dans ces derniers. Il devient alors très simple d'accèder à la valeur d'un cookie en appellant le tableau $_COOKIE avec la clé qui convient. L'exemple ci-dessous nous permet de récupérer la valeur du cookie que nous avions créé précédemment.
Lecture d'un cookie<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"><title>Lecture d'un cookie !</title></head>Votre thème favoris est :<?php// Lecture de la valeur du cookie designPrefereecho $_COOKIE['designPrefere']; // Affiche 'prairie'?></p></body></html>
Remarques :
[1] Ajouter un couple clé / valeur au tableau $_COOKIE ne crée pas de nouveau cookie.
[2] Pour modifier la valeur d'un cookie, il faut réutiliser la fonction setcookie().
[3] Pour connaître tous les cookies utilisés, il faut lister le tableau $_COOKIE au moyen d'une boucle foreach() ou d'un appel à print_r().
Suppression d'un cookie
Pour supprimer un cookie, il faut de nouveau appeller la fonction setcookie() en lui passant en paramètre le nom du cookie uniquement. Dans notre exemple, nous utiliserons le code suivant pour supprimer notre cookie designPrefere.
Script de suppression d'un cookie<?php// Suppression du cookie designPrefere?>
Le code précédent demande au navigateur d'effacer le cookie mais ne supprime pas la valeur présente dans le tableau $_COOKIE. Il faut donc penser à supprimer les deux. Pour cela, nous utilisons le script ci-après.
Script de suppression complète d'un cookie<?php// Suppression du cookie designPrefere// Suppression de la valeur du tableau $_COOKIE?>
Stocker des types complexes dans un cookie
Jusqu'à maintenant nous avons stocké dans notre cookie une valeur de type chaine de caractères. C'est donc un type primitif. Mais il est aussi possible de stocker un tableau entier dans un cookie. Pour réaliser cette opération, il faut obligatoirement transformer ce dernier en chaine de caractères puis le reconstruire lors de sa réception. C'est ce que l'on appelle la sérialisation (ou encore pliage, marshalling) et la désérialisation (ou encore dépliage ou unmarshalling). Ces deux opérations sont réalisées au moyen des fonctions serialize() et unserialize().
Illustrons ces principes à partir d'un exemple simulant le lancé d'un dé. Notre cookie s'appellera "lancesDe". Nous simulerons également les lancés du dé avec la fonction rand(). Tous les lancés seront stockés dans un vecteur (tableau à une dimension indexé numériquement) que nous sérialiserons / désérialiserons pour les besoins du cookie.
Simulation de lancés de dé et enregistrement des scores dans un cookie<?php// Définition des structures de données$nombreLancesDe = 0; // Nombre de lances de dé$listeSerialisee = ''; // Chaine serialisee du cookie$listeLancesDe = array(); // Tableau des valeurs de lancés de dé// Test de l'existence du cookieif(!empty($_COOKIE['lancesDe'])){// On récupère les valeurs dans $listeLancesDe par désérialisation$listeSerialisee = $_COOKIE['lancesDe'];$listeLancesDe = unserialize($listeSerialisee);}// On lance une nouvelle fois le dé$listeLancesDe[] = rand(1,6);// On sérialise le tableau et on crée le cookie$listeSerialisee = serialize($listeLancesDe);setcookie('lancesDe', $listeSerialisee, time()+3600*24);// On calcule le nombre de lancés de dé$nombreLancesDe = count($listeLancesDe);?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"><head><title>Simulation de lancés d'un dé !</title></head><body><p>Vous avez lancé <?php echo $nombreLancesDe; ?> fois le dé :</p><?phpif($nombreLancesDe > 0){echo '<ul>';// On affiche le contenu du tableau désérialiséforeach($listeLancesDe as $numeroLance => $valeurLance){echo '<li>Lancé n#', ($numeroLance+1) ,' : ', $valeurLance ,'</li>';}echo '</ul>';}?></body></html>
En appellant cinq fois le script, nous simulons cinq lancés de dé. Le résultat produit est similaire à celui-ci.
Résultat de l'exécution du scriptVous avez lancé 5 fois le dé :* Lancé #1 : 4* Lancé #2 : 6* Lancé #3 : 3* Lancé #4 : 3* Lancé #5 : 3* Lancé #6 : 2
Les principaux cas d'utilisation des cookies
Les cookies se révèlent donc très utiles dans des cas de figure particuliers. Parmi eux, nous pouvons recenser :
- la sauvegarde du design préféré d'un site pour un internaute
- l'affichage les nouveaux messages depuis la dernière visite de l'internaute
- l'affichage les messages non-lus par le visiteur dans un forum
- la fragmentation d'un formulaire sur plusieurs pages. Les valeurs envoyées sur la première page sont sérialisées et envoyées par cookie à la seconde qui les désérialisera
- les compteurs de visites
- la reconnaissance des visiteurs ayant déjà voté à un sondage
- ...
Conclusion
Nous retiendrons que les cookies sont un moyen efficace de retenir des informations de faible importance concernant un utilisateur. Néanmoins, pour des raions de sécurité, leur taille est limitée à 4Ko et leur nombre à 20 pour un même domaine. Il ne faut donc pas les utiliser pour transférer des données nombreuses mais uniquement pour stocker des informations à but statistique ou de personnalisation d'affichage.
Les commentaires
2. Par alibaba le 28/06/2009 23:25
Bonsoir Emacs
Dans la conclusion, la ligne 'Néanmoins, pour des raions de sécurité,...' contient une petite faute.
Vous avez oublié le 's' (raion).
Les cookies sont delicieux merci Emacs!
1. Par saturn2 le 29/12/2007 01:03