La gestion des sessions en PHP

Les sessions en PHP sont gouvernées par plusieurs éléments qui peuvent travailler ensemble ou entrer en conflit.

Tous les paramètres de PHP ci-dessous sont configurables dans php.ini, dans le vhost (si l'on utilise modPHP d'Apache) ou dans le .htaccess (si on autorise les .htaccess).

Explication générale

Quand nous chargeons (dans un navigateur) un site en PHP, le mécanisme par défaut du site est de démarrer une "session", c'est-à-dire un petit espace de stockage d'informations sur nous qui pourra être réutilisé sur les pages suivantes, ce qui permet au serveur de "se souvenir" de nous. Ainsi, la page suivante n'a plus, par exemple, besoin de nous demander qui nous sommes au travers d'un nom d'utilisateur et d'un mot de passe. Côté serveur, ces valeurs sont stockées (généralement dans un fichier individuel par session utilisateur). Pour que le serveur reconnaisse le navigateur qui a consulté une page antérieure, il stocke dans le navigateur un numéro de session au travers du mécanisme connu de "cookie". Un cookie est aussi une façon de stocker des informations dans le navigateur, mais par sécurité (confidentialité des données) on n'y stocke souvent que des informations brêves et non personnelles, comme un... numéro de session.

Le cookie est alors réutilisé pour toute requête vers le même site (URL) : le navigateur envoie systématiquement le cookie lorsque l'utilisateur consulte toute autre page du site, et le serveur prend automatiquement en compte le cookie qui porte un nom accordé pour le nom des cookies de session, retrouve le fichier correspondant sur le disque et le charge en mémoire avant de continuer l'exécution du code PHP.

Ce mécanisme n'existe pas qu'en PHP, mais chaque langage a la responsabilité de gérer ça à sa manière.

En PHP, on décide de variations du mécanisme de gestion des sessions au travers d'options de configuration sur le serveur. On peut, par exemple, décider que les sessions seront stockées sur un serveur Redis (souvent utilisé quand on a plusieurs serveurs web pour un même site et qu'on souhaite que n'importe quel utilisateur ait une expérience unifiée, peu importe le serveur sur lequel sa requête est envoyée.

Par défaut, PHP stocke ces sessions dans un répertoire (souvent /var/lib/php/sessions, sous Linux) et leur donne une durée de vie de 24 minutes (ou 1440 secondes, puisque les paramètres sont stockés en secondes).

À chaque utilisation de cette session (chaque page chargée, par exemple), le compteur est mis à jour pour que ça dure 24 minutes de plus.

Côté client, s'il n'y a plus aucune activité (= chargement de page, par exemple) pendant 24 minutes, alors le cookie (initialement marqué pour une durée de 24 minutes) n'est plus valable et le navigateur ne l'envoie même plus au serveur lors d'une nouvelle requête, et on dit que "la session a expiré". Le site demandera probablement à l'utilisateur de s'identifier à nouveau.

Côté serveur, c'est un peu similaire, et c'est fait comme une mesure de prudence : le serveur considère comme expirés tous les fichiers de sessions qui n'ont pas été "touchés" (consultés ou modifiés) dans les dernières 24 minutes. Mais, et c'est très important pour comprendre le mécanisme dans son ensemble, les fichiers correspondants ne sont pas automatiquement supprimés après 24 minutes. Ça va dépendre du nombre de visites sur le site comme de la "probabilité" de démarrage d'un mécanisme appelé le "garbage collector" (ou "gc"), soit le "ramasseur de poubelles" de PHP, qui est un processus qui est lancé ou pas à chaque nouvelle visite sur le site. Ce sont les paramètres suivants qui vont décider de ce mécanisme.

Côté serveur

session.gc_probability

Ce paramètre de configuration de PHP spécifie la probabilité, exprimée en pourcentage et en conjonction avec session.gc_divisor (voir ci-dessous), que la routine gc (garbage collection, le "ramasseur de poubelles") soit démarrée à chaque requête. La valeur par défaut est 1. La valeur doit être supérieure ou égale à 0.

session.gc_divisor

Ce paramètre de configuration de PHP spécifie, en conjonction avec session.gc_probability ci-dessus, la probabilité que la routine gc (garbage collection) soit démarrée à chaque début de session. La probabilité est calculée en utilisant gc_probability/gc_divisor, par exemple 1/100 signifie qu'il y a 1% de chance pour que la routine gc démarre à chaque requête. La valeur par défaut est 100. La valeur doit être supérieure ou égale à 0.

session.gc_maxlifetime

Ce paramètre de configuration de PHP spécifie la durée de vie des données sur le serveur, en nombre de secondes. Après cette durée, les données seront considérées comme obsolètes, et pourront être supprimées (par le garbage collector). Les données peuvent ainsi devenir obsolètes lors du démarrage de la session (selon gc_probability et gc_divisor). La valeur par défaut est de 1440 secondes (24 minutes). Attention, si plusieurs scripts modifient gc_maxlifetime alors qu'ils agissent sur la même session utilisateur, c'est la valeur la plus petite qui est prise en compte.

session.save_path

Ce paramètre de configuration de PHP permet de choisir où stocker les fichiers de sessions sur le serveur. Nous le mentionnons ici parce que, si vous l'utilisez avec son paramètre optionnel du nombre de sous-répertoires (du genre de "2;/tmp"), le garbage collector par défaut n'est plus exécuté, donc les explications ci-dessus n'ont plus lieu d'être.

Côté client

session.cookie_lifetime

Ce paramètre de configuration de PHP permet de donner un temps d'expiration au cookie qui identifie la session PHP (voir "Explication générale" ci-dessus). Ce paramètre peut être mis à "0", et dans ce cas c'est simplement la fermeture de la fenêtre ou de l'onglet du navigateur qui fera automatiquement expirer le cookie.

Règle de bon sens

Vous l'aurez compris, idéalement, session.cookie_lifetime et session.gc_maxlifetime devraient avoir la même valeur, ou gc_maxlifetime pourrait avoir une valeur spécifique différence si session.cookie_lifetime est à 0 (parce que dans ce cas c'est la fermeture de la fenêtre/onglet du navigateur qui déclenche la suppression du cookie mais qu'on pourrait quand même vouloir mettre une mesure de sécurité en plus côté serveur au cas où l'utilisateur laissait son onglet ouvert pendant 1 an).

Le côté obscur des cookies

Ce mécanisme fonctionne bien, depuis des dizaines d'années, mais il reste à observer quelques détails concernant sa dépendance aux cookies :

  • les cookies sont des informations gardées du côté du client et sont très facilement modifiables. Ils ne sont donc pas super fiables et il est important que les identifiants de sessions soient difficiles à "deviner" (c'est pour ça qu'il s'agit habituellement de longues chaînes de caractères).
  • dans la même pensée, ces cookies peuvent être lus et modifiés par du JavaScript qui tournerait sur la page, que ce soit du site que vous consultez, ou au travers d'extensions de votre navigateur ou encore via un hack qui aurait pour objectif d'exécuter du code "rebelle" depuis la page d'un site en lequel vous avez confiance (attaques type XSS ou CSRF). Certains sites mettent donc en place des mécanismes de vérification de l'authenticité des données dans les cookies pour éviter toute modification non-souhaitée côté client.
  • les cookies transitent à chaque appel (même deux fois : une à l'envoi de la requête, une à la réception de la réponse), il est donc important, pour éviter les vols de sessions (communément appelés "session hi-jacking" en anglais) de sécuriser la ligne avec une encryption valable en HTTPS (attention, beaucoup d'algorithmes sous-jacents d'HTTPS sont maintenant invalides, il faut donc mettre à jour de temps en temps les algorithmes utilisés derrière HTTPS).
  • comme les cookies transitent à chaque appel, il est important de ne pas les utiliser pour stocker tout un tas d'informations qui pourraient rester sur le serveur, parce que ça évite du transfert de données, qui peut ralentir le chargement du site.

Note commerciale

Malgré notre spécialisation dans le monde du e-learning de logiciel libre, nous sommes avant tout experts en technologies du web. Si vous avez des problèmes complexes à résoudre, BeezNest peut intervenir à un niveau de complexité élevé pour offrir des solutions à vos problèmes techniques, tant de sécurité que d'optimisation du chargement des pages de votre site. Contactez-nous via notre formulaire web pour plus d'infos.