The Tech Guy FR

[PHP] Les sessions

par c2c le 9 mar 2009

Les sessions PHP

Les sessions PHP

Les sessions sont présentes dans PHP depuis PHP4 (1998) et font partie des première choses que l’ont apprend à utiliser, cependant, elles sont souvent très mal utilisées car mal comprises ; l’occasion de revenir sur ce sujet et me lancer dans un premier article « pédagogique ».

Pourquoi utiliser des sessions

Comprendre ce point, c’est éviter pas mal de bourdes. Qu’est-ce qu’une session exactement ?

Une session, comme son nom l’indique, représente un temps défini d’utilisation d’un site par un internaute donné. Cette session à donc un début et une fin et représente un temps logique d’utilisation.

Les sites Web reposent sur un protocole : HTTP, qui est de nature très volatile => Je me connecte, j’envoi une requête, le serveur me répond, je me déconnecte. Impossible de savoir qui vous êtes !Pour pallier à ce problème ont été inventés les cookies. Un cookie est un « témoin » que laisse un serveur Web dans votre navigateur, cela permet de mettre en place un historique de la communication.

Les sessions ont le même but, garder un historique des communications entre le serveur Web et votre navigateur. Ce n’est ni un espace de stockage temporaire, ni une base de données.

Comment fonctionnent les sessions

Côté PHP, rien de plus simple :

/**
 * Création de la session
 */
session_start();
/**
 * Créer / Modifier une donnée de session
 */
$_SESSION['user_id'] = 125;
/**
 * Supprimer une donnée de session
 */
unset($_SESSION['user_id']);
/**
 * Détruire une session
 */
session_destroy();

Je vous laisse consulter la liste des fonctions complète …

Mais comment cela fonctionne-t-il concrètement ? Analysons le fonctionnement par défaut :

Lors du premier appel à session_create(), PHP va créer un fichier temporaire dont le nom est un identifiant unique. Cet identifiant est également l’identifiant de le session. Il va également envoyer un cookie au navigateur nommé PHPSESSID contenant cet identifiant unique.

Une fois ce fichier créé, PHP va alors rendre disponible un variable superglobale (disponible quel que soit le contexte) $_SESSION. Le développeur peut alors utiliser ce tableau comme n’importe lequel pour y stocker, lire et supprimer des données.

A la fin de l’execution du script, PHP va écrire dans le fichier temporaire créé lors de la première étape le contenu du tableau $_SESSION linéarisé.

Lors des prochaines requêtes, le navigateur va envoyer l’identifiant de la session (stocké dans le cookie PHPSESSID), session_create() ne créera pas alors de fichier mais délinéarisera le contenu de ce fichier et le stockera dans $_SESSION, le développeur pourra alors récupérer les données stockées lors de la requête précédente et les modifier à nouveau. Ce jusqu’a l’appel de session_destroy() qui effacera le fichier temporaire et le cookie.

Comme l’on vient de le voir, le système des sessions est basé sur les cookies. Un cookie est donné du serveur Web au navigateur par une en-tête HTTP. Il est donc impératif de placer l’appel à session_start() le plus haut possible dans votre script, car toute information envoyée (echo(), imagejpeg(), …) provoquera l’envoi définif des en-tête standard et il sera trop tard pour envoyer le cookie de session !

Ce qu’une session doit contenir

Maintenant que nous avons une nouvelle opportunité, à savoir stocker des données entre deux requête d’un utilisateur, on pourrait avoir le reflexe d’y enregistrer tout un tas de chose, comme l’historique de navigation de l’internaute sur le site, ses précédents achats, etc.

STOP.

Une session n’est pas un espace de stockage ou une mémoire cache. Le fonctionnement décrit ci-dessus est très pratique mais très gourmand en ressources :

  • Les données sont à chaque requête linéarisée et délinéarisées. Si cette fonction est très pratique pour enregistrer une données complexe facilement (transformée en une chaîne), elle est très couteuse en ressources
  • Les données linéarisées sont stockées sur un fichier. Il y a donc pour chaque requête une écriture et une lecture sur le disque dur. Les opérations sur le disque dur sont les première opérations à minimiser si l’on veut optimiser son site
  • Le tableau $_SESSION est une superglobale, ce qui veut dire qu’il sera accessible de partout mais aussi qu’il sera présent en mémoire tout au long de l’execution du script. Garder beaucoup d’informations en mémoire quand elles ne sont pas utilisées est un non sens. Celles-ci doivent être présente que lorsqu’on l’utilise est déchargées dès que possible.

Une session ne doit donc contenir qu’une chose : Des informations sur la session en cours, typiquement peut s’agir :

  • D’un identifiant utilisateur
  • Un email
  • Une clef unique
  • La date de création de la session

Configuration et scaling

Le fonctionnement des sessions vu ci-dessus n’est pas gravé dans le marbre. Et heureusement.Si il a le mérité d’être simple à utiliser, il est totalement inutilisable sur des sites à gros traffic.

Configurer le cookie

Le nom par défaut du cookie des sessions est PHPSESSID. Simple, clair, on sait de quoi il s’agit. Un peu trop même. Cela peut être changé en utilisant la fonction session_name() ou la variable de configuration session.name.

Mais il y a plus grave, ce cookie est défini par défaut comme ceci :

  • Il n’est valable que pour le domaine (VHOST) en cours (donc si vous changez de domaine => en.monsite.com vers fr.monsite.com, il n’est plus valable)
  • Il est valable des la racine ‘/’ (Si votre site est www.site.com/monsite/, vous le partagez avec www.site.com/autresite/)
  • C’est un cookie de session (Des que le navigateur est fermé, il n’est plus valable)
  • Il est valable qu’on soit en HTTP ou HTTPS

Pour configurer ça, nous avons la méthode

session_set_cookie_params($lifetime, $path, $domain, $secure, $httponly);
  • $lifetime : Si 0, cookie de session, sinon, le nombre de secondes pendant lequel il sera valable [Default: 0]
  • $path : Définit la racine du chemin a partir duquel le cookie sera valide (Ex: ‘/monsite’) [Default: '/']
  • $domain : Domaine pour lequel le cookie sera valable. Pour tous les domaines se terminant par ‘juliencrouzet.fr’, utilisez ‘.juliencrouzet.fr’ [Default: Le VHOST en cours]
  • $secure : Si true, le cookie ne sera envoyé que si l’on est en HTTPS [Default: false]
  • $httponly : Si true, le cookie ne sera envoyé que si le protocole est HTTP (Pas dans le cas d’une demande de script ou de feuille CSS, comme c’est le cas sur les attaques XSS) [Default: false]

Modifier la gestion des cookie

PHP est livré avec le système de session géré par fichier temporaire comme décrit plus haut.  Cependant, comme nous l’avons rappelé, ce système est couteux en ressources et inadapté à des sites professionnels à forts traffic.

Heureusement, tout à été prévu ! La fonction session_set_save_handler() vous permet de gérer vous même la création, la destruction est la manipulation des sessions et ainsi les stocker dans :

  • Une base de données MySQL, SQLite, etc.
  • Un système de cache (Attention cependant, un cache est volatile et peut disparaitre, vos sessions aussi !)
  • Ce que vous voulez !

Scaling de votre application

Si modifier la gestion des sessions peut paraitre un best practice si l’on a qu’un serveur, elle devient indispensable si l’on a plusieurs serveurs !

Une session est propre à un site Internet, pas à une machine, et si la session est stockée sur le disque dur de la première machine ou l’a fait une requête, elle aura disparue des que l’on change de serveur !

Sécuriser des sessions

Les sessions servant essentiellement à authentifier un internaute, il est primordial de vérifier leur sécurité. Une des première faille du système repose sur le fait qu’il suffise de connaitre l’identifiant de la session d’un internaute pour usurper son identité. C’est moche.

Une des premières idées que l’on peut avoir est de couplé cet identifiant à une adresse I.P., mais quid des utilisateurs en entreprise qui sont souvent derrière un pool de proxy et donc qui changent régulierement d’I.P. ?

La plus importante règle de sécurité à appliquer est en fait de regénérer l’identifiant de session à chaque requête. Certes, le cookie change à chaque fois et cela peut être un peu gourmand en ressources, mais si quelqu’un arrive à récupérer votre identifiant, cela ne lui sert a rien, il aura déjà changé lors de la prochaine requête.

Il suffit pour cela d’utiliser session_regenerate_id() – ou – utiliser Zend Framework ! (oui je sais c’est récurrent ça)

:, , ,

1 commentaire

  • Jay

    Attention petite coquille, il s’agit de session_start et non pas de session_create qui n’existe pas.

    Petit détail sur la sécurité des sessions, si le serveur héberge plusieurs sites, penser a faire des dossiers différents pour le stockage des sessions pour chaque site, ca évitera le vol de session en passant par un site plus faillible.

Commentez, insultez, réagissez !

XHTML: Vous pouvez utiliser ces balises: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Une recherche ?

Utilisez le formulaire pour rechercher un article :

Si vous ne trouvez toujours pas ce que vous cherchez, n'hésitez pas à me contacter : contact.blog@juliencrouzet.fr