CXI. Sessions

Introduction

Le support des sessions de PHP est un moyen de préserver des données entre plusieurs accès. Cela vous permet de créer des applications personnalisées, et d'augmenter l'attrait de votre site.

Chaque visiteur accédant à votre page web se voit assigné un identifiant unique, appelé "identifiant de session". Il peut être stocké soit dans un cookie, soit propagé dans l'URL.

Le support des sessions vous permet d'enregistrer un nombre illimité de variables qui doivent être préservées entre les requêtes. Lorsqu'un visiteur accède à votre site, PHP va vérifier automatiquement (si session.auto_start est activé) ou sur demande (explicitement avec session_start() ou implicitement avec session_register()) s'il existe une session du même nom. Si c'est le cas, l'environnement précédemment sauvé sera recréé.

Attention

Si vous activé session.auto_start , alors vous ne pourrez pas enregistrer d'objets dans votre session tant que la définition de la classe ne sera pas chargée avant le début de la session, pour recréer les objets de votre session.

Toutes les variables sont sérialisées après l'exécution du script PHP. Les variables qui sont indéfinies sont marquées comme telles. Lors des accès ultérieurs, elles ne seront pas définies, jusqu'à ce que l'utilisateur le fasse.

Avertissement

Quelques types de données ne peuvent pas être linéarisés pour être stockés dans les sessions. Cela inclut les variables de type resource ou les objets avec des références circulaires (i.e. objets qui passent une référence à lui-même à un autre objet).

Note : La gestion des sessions a été ajoutée en PHP 4.0.

Note : Notez que lorsque vous travaillez avec les sessions, un enregistrement dans la session ne sera pas créé tant que la variable ne sera pas enregistré en utilisant la fonction session_register() ou en ajoutant une clé à la variable super-globale $_SESSION. Cela n'est vrai que si vous avez débuté une session en appelant la fonction session_start().

Sessions et sécurité

Lien externe : Session fixation

Utiliser les sessions ne signifie pas que les données de session ne pourront être vue que par un seul utilisateur. Il est important de garder cela en tête, lorsque vous stockez et affichez des données importantes. Lorsque vous stockez des données dans une session, il faut se demander quels seront les problèmes posés si quelqu'un d'autre accède à cette information, ou comment votre application est affectée si la session est en fait celle d'un autre.

Par exemple, si quelqu'un usurpe une session, il peut alors poster un message dans un forum sous une fausse identité. Quelle est la gravité de ce problème? Ou bien, il peut accéder aux commandes d'un client, et même, modifier son panier d'achat. A priori, c'est moins problématique pour un fleuriste que pour un pharmacien. Si vous voulez résoudre ce souci de façon simple, il peut être utile d'activer session.use_only_cookies. Dans ce cas, les cookies devront être activés par le client, sinon, les sessions ne fonctionneront pas.

Par conséquent, lorsque vous manipulez des données importantes, il faut exploiter d'autres méthodes pour décider si une session est valide ou pas. Les sessions ne fournissent pas une méthode fiable d'identification.

Les sessions reposent sur un identifiant de session, ce qui signifie que quelqu'un peut voler cet identifiant, rien qu'en volant l'ID. Ce vol peut être rendu très difficile, comme en utilisant les cookies, mais en aucun cas cela sera impossible. Les sessions dépendent aussi de la discipline de l'utilisateur qui referme son navigateur à la fin de la session pour tout clore proprement. De plus, même les cookies de session peuvent être surveillés sur un réseau, ou bien notés par un proxy car ils transitent en clair sur le réseau. Pour remédier à cela, vous devriez implémenter un chiffrage SSL sur votre plate-forme.

Pré-requis

Ces fonctions sont disponibles dans le module PHP standard, qui est toujours accessible.

Note : Optionnellement, vous pouvez utiliser l'allocation de mémoire partagée (mm), développé par Ralf S.Engelschall, pour stocker votre session. Vous devez télécharger mm et l'installer. Cette option n'est pas disponible pour les environnements Windows. Notez que le module de stockage de session mm ne garantit pas les verrous de sessions en cas d'accès multiples à la même session. Il peut être moins approprié d'utiliser un système de fichiers basé en mémoire partagée (comme tmpfs sur Solaris/Linux ou /dev/md sur BSD) pour stocker les sessions dans des fichiers, car ils ne seront pas proprement verrouillés.

Installation

Le support des sessions est activé par défaut. Si vous souhaitez exclure le support des sessions de PHP, vous devez utiliser l'option --disable-session lors de l'exécution du script de configuration. Pour utiliser la mémoire vive pour le stockage des sessions, compilez PHP avec l'option --with-mm[=DIR] .

La version Windows de PHP dispose du support automatique de cette extension. Vous n'avez pas à ajouter de bibliothèque supplémentaire pour disposer de ces fonctions.

Note : Par défaut, toutes les données relatives à une session particulière seront stockées dans un fichier du répertoire spécifié par session.save_path dans les options du fichier php.ini. Un fichier pour chaque session sera créé. Cela est dû au fait que une session est ouverte (un fichier est créé) mais aucune donnée n'est écrite dans ce fichier. Notez que ce comportement est un effet des limitations d'utilisation du système de fichiers et il est possible qu'un gestionnaire de session personnalisé (par exemple, un qui utilise une base de données) ne garde aucune trace des sessions où aucune donnée n'y a été enregistrée.

Configuration à l'exécution

Le comportement de ces fonctions est affecté par la configuration dans le fichier php.ini.

Tableau 1. Options de configuration

NomPar défautModifiable
session.save_path"/tmp"PHP_INI_ALL
session.name"PHPSESSID"PHP_INI_ALL
session.save_handler"files"PHP_INI_ALL
session.auto_start"0"PHP_INI_ALL
session.gc_probability"1"PHP_INI_ALL
session.gc_divisor"100"PHP_INI_ALL
session.gc_maxlifetime"1440"PHP_INI_ALL
session.serialize_handler"php"PHP_INI_ALL
session.cookie_lifetime"0"PHP_INI_ALL
session.cookie_path"/"PHP_INI_ALL
session.cookie_domain""PHP_INI_ALL
session.cookie_secure""PHP_INI_ALL
session.use_cookies"1"PHP_INI_ALL
session.use_only_cookies"0"PHP_INI_ALL
session.referer_check""PHP_INI_ALL
session.entropy_file""PHP_INI_ALL
session.entropy_length"0"PHP_INI_ALL
session.cache_limiter"nocache"PHP_INI_ALL
session.cache_expire"180"PHP_INI_ALL
session.use_trans_sid"0"PHP_INI_ALL
session.bug_compat_42"1"PHP_INI_ALL
session.bug_compat_warn"1"PHP_INI_ALL
session.hash_function"0"PHP_INI_ALL
session.hash_bits_per_character"4"PHP_INI_ALL
url_rewriter.tags"a=href,area=href,frame=src,form=,fieldset="PHP_INI_ALL
Pour plus de détails sur les constantes PHP_INI_*, reportez-vous à ini_set().

Le système de sessions dispose d'un grand nombre de directives dans le fichier php.ini. En voici une présentation :

session.save_handler string

Définit le nom du gestionnaire de session qui est utilisé pour stocker et relire les données. Par défaut, c'est le système intégré par fichiers : files. Voir aussi session_set_save_handler().

session.save_path string

Définit le chemin qui doit être passé au gestionnaire de sauvegarde. Si vous décidez de choisir le gestionnaire par défaut (par fichier), cet argument sera utilisé comme dossier de sauvegarde des sessions. Par défaut, il vaut /tmp. Voir aussi session_save_path().

Il y a un argument optionnel N à cette directive qui détermine la profondeur de répertoires où votre fichier de session sera stocké. Par exemple, si vous définissez '5;/tmp', votre fichier sera situé dans /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If . Si vous voulez utiliser N, vous devez créer tous ces répertoires avant de les utiliser. Un petit script shell existe dans ext/session pour réaliser ces créations et il se nomme mod_files.sh. Notez également que si N est utilisé et est supérieur à 0, alors la routine automatique gc (garbage collection) ne sera pas exécuté ; voir une copie de php.ini pour plus d'informations. Egalement, si vous utilisez N, assurez-vous d'entourer session.save_path de "doubles guillemets" car le séparateur (;) est également utilisé pour les commentaires dans php.ini.

Avertissement

Si vous laissez cette option configurée avec un dossier accessible en lecture à tout le monde, comme /tmp (par défaut), les autres utilisateurs pourront exploiter ces sessions en obtenant la liste de fichiers dans ce dossier.

Note : Avant PHP 4.3.6;, les utilisateurs de Windows doivent changer cette valeur de variable pour que les fonctions de sessions de PHP fonctionnent. Indiquez un chemin de dossier valide, par exemple : c:/temp.

session.name string

Spécifie le nom de la session, qui sera utilisé comme nom de cookie. Il ne doit contenir que des caractères alphanumérique. Par défaut, c'est PHPSESSID. Voir aussi session_name().

session.auto_start boolean

Spécifie si le module de session doit démarrer automatiquement au début de chaque script PHP. Par défaut, c'est 0 (désactivé).

session.serialize_handler string

Définit le nom du gestionnaire qui est utilisé pour linéariser/délinéariser les données. Actuellement, un format interne à PHP (nommé php) et WDDX (nommé wddx) sont supportés . WDDX est seulement disponible, si PHP a été compilé avec l'option WDDX. Par défaut, c'est php.

session.gc_probability entier

Spécifie la probabilité, exprimée en pourcentage, en conjonction de session.gc_divisor, que la routine gc (garbage collection) soit démarrée à chaque requête. La valeur par défaut est 1. Voir session.gc_divisor pour plus de détails.

session.gc_divisor entier

session.gc_divisor en conjonction de session.gc_divisor définie la probabilité que la routine gc (garbage collection) soit démarré à chaque début de session. La probabilité est calculé en utilisant gc_probability/gc_divisor, e.g 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.

session.gc_maxlifetime entier

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 supprimées.

Note : Si vous utilisez le gestionnaire de session par fichier, qui est fourni par défaut votre système doit garder la trace des dates de dernier accès aux fichier (atime). La FAT de Windows ne le fait pas, alors il vous faudra trouver un autre système pour gérer les sessions qui ont expirées. Depuis PHP 4.2.3, on utilise mtime (date de modification) au lieu de atime. Donc, vous n'aurez plus de souci avec les systèmes de fichiers qui ne gèrent pas atime.

session.referer_check entier

Contient une sous-chaîne que vous souhaitez retrouver dans tous les en-têtes HTTP Referer. Si cet en-tête a été envoyé par le client, et que la sous-chaîne n'a pas été trouvé, l'identifiant de session sera considéré comme invalide. Par défaut, cette option est une chaîne vide.

session.entropy_file string

Est un chemin jusqu'à une source externe (un fichier), qui sera utilisée comme source additionnelle d'entropie pour la création de l'identifiant de session. Des exemples valides sont /dev/random et /dev/urandom, qui sont disponibles sur tous les systèmes Unix.

session.entropy_length entier

Spécifie le nombre d'octets qui seront lus dans le fichier défini ci-dessus. Par défaut, il vaut 0, c'est à dire inactif.

session.use_cookies boolean

Spécifie si le module utilisera les cookies pour stocker les données de session sur le client. Par défaut, il vaut 1, c'est à dire actif.

session.use_only_cookies boolean

Spécifie si le module doit utiliser seulement les cookies pour stocker les identifiants de sessions du coté du navigateur. Par défaut, cette option vaut 0 (inactif, pour compatibilité ascendante). En l'activant, vous éviterez les attaques qui utilisent des identifiants de sessions dans les URL. Cette configuration a été ajoutée en PHP 4.3.0.

session.cookie_lifetime entier

Spécifie la durée de vie du cookie en secondes. La valeur de 0 signifie : "Jusqu'à ce que le navigateur soit éteint". La valeur par défaut est : 0. Voir aussi session_get_cookie_params() et session_set_cookie_params().

session.cookie_path string

Spécifie le chemin utilisé lors de la création du cookie. Par défaut, il vaut /. Voir aussi session_get_cookie_params() et session_set_cookie_params().

session.cookie_domain string

Spécifie le domaine utilisé lors de la création du cookie. Par défaut, il ne vaut rien. Voir aussi session_get_cookie_params() et session_set_cookie_params().

session.cookie_secure boolean

Spécifie que les cookies ne doivent être émis que sur des connexion sécurisée. Par défaut, cette option est à off. Cette option a été ajoutée en PHP 4.0.4. Voir aussi session_get_cookie_params() et session_set_cookie_params().

session.cache_limiter string

Spécifie le type de contrôle de cache utilisé pour les pages avec sessions. Les valeurs possibles sont : none, nocache, private, private_no_expire, public. Par défaut, il vaut nocache. Voir aussi session_cache_limiter().

session.cache_expire entier

Spécifie la durée de vie des données de sessions, en minute. Cette option n'a aucune conséquence sur le contrôle de cache. Par défaut, il vaut 180 (3 heures). Voir aussi session_cache_expire().

session.use_trans_sid boolean

Spécifie si le support du SID est transparent ou pas. Par défaut vaut 0 (désactivé).

Note : En PHP 4.1.2 ou plus ancien, cette option est activée en utilisant l'option de compilation --enable-trans-sid. Depuis PHP 4.2.0, cette option est toujours activée.

Le système de gestion des sessions par URL pose un risque supplémentaire de sécurité : un utilisateur peut envoyer son URL avec l'identifiant de session par email à un ami, ou bien le mettre dans ses signets. Cela diffusera alors l'identifiant de session.

session.bug_compat_42 boolean

Les versions de PHP antérieures à la version 4.2.0 disposaient d'une fonctionnalité/bogue non documentée, qui vous permettait d'initialiser une variable de session dans le contexte global, même si register_globals était désactivé. PHP 4.3.0 et plus récent vous préviendra de l'utilisation de cette fonctionnalité si vous avez aussi activé session.bug_compat_warn.

session.bug_compat_warn boolean

Les versions de PHP antérieures à la version 4.2.0 disposaient d'une fonctionnalité/bogue non-documentée, qui vous permettait d'initialiser une variable de session dans le contexte global, même si register_globals était désactivé. PHP 4.3.0 et plus récent vous préviendra de l'utilisation de cette fonctionnalité si vous avez activé session.bug_compat_42 et session.bug_compat_warn.

session.hash_function entier

session.hash_function vous permet de spécifier la fonction de hachage à utiliser pour générer les identifiants de session. '0' signifie MD5 (128 bits) et '1' signifie SHA-1 (160 bits).

Note : Cette directive a été ajoutée en PHP 5.

session.hash_bits_per_character entier

session.hash_bits_per_character vous permet de définir le nombre de bits utilisés pour chaque caractère lors des conversions des données binaires en éléments lisibles. Les valeurs possibles sont '4' (0-9, a-f), '5' (0-9, a-v), et '6' (0-9, a-z, A-Z, "-", ",").

Note : Cette directive a été ajoutée en PHP 5.

session.url_rewriter.tags string

Spécifie quels sont les balises HTML qui doivent être réécrites si le support transparent du SID est activé. Par défaut, il vaut a=href,area=href,frame=src,input=src,form=fakeentry,fieldset=.

Note : Si vous voulez vous conformer avec les spécifications XHTML, supprimer l'entrée form et utiliser le tag <fieldset> autour de votre balise form.

Les options track_vars et register_globals influencent le comportement des sessions, leur stockage et leur restauration.

Note : Depuis PHP 4.0.3, track_vars est toujours activé.

Types de ressources

Cette extension ne définit aucune ressource.

Constantes pré-définies

Ces constantes sont définies par cette extension, et ne sont disponibles que si cette extension a été compilée avec PHP, ou bien chargée au moment de l'exécution.

SID (chaîne de caractères)

Constante contenant le nom de la session et l'identifiant en cours, sous la forme "name=ID" ou une chaîne vide si l'identifiant de session a été défini dans un cookie de session.

Exemples

Note : Depuis PHP 4.1.0, $_SESSION est disponible comme variable globale, au même titre que $_POST, $_GET, $_REQUEST, etc. Contrairement à $HTTP_SESSION_VARS, $_SESSION est toujours globale. Par conséquent, vous n'avez pas besoin d'utiliser le mot réservé global avec $_SESSION. Notez que cette documentation a été modifiée pour utiliser $_SESSION. Vous pouvez toujours le remplacer par $HTTP_SESSION_VARS si vous préférez l'ancienne version. Notez également vous devez démarrer votre session en utilisant la fonction session_start() avant d'utiliser la variable super-globale $_SESSION.

Les clés du tableau $_SESSION sont sujettes aux mêmes limitations que les variables PHP habituelles, c'est à dire qu'elles ne peuvent pas commencer par un nombre, mais commencer par une lettre ou un souligné '_'. Pour plus de détails, reportez-vous à la section sur les variables.

Si track_vars est activé et register_globals est désactivé, seuls les éléments du tableau global $_SESSION contiendront les variables enregistrées dans la session. Les variables de sessions relues seront uniquement disponibles dans $_SESSION.

L'utilisation de $_SESSION (ou $HTTP_SESSION_VARS avec PHP 4.0.6 et plus ancien) est recommandé pour une meilleure sécurité et un code plus facilement entretenu. Avec $_SESSION, il n'y a pas besoin d'utiliser les fonctions session_register(), session_unregister() et session_is_registered(). Les variables de sessions sont accessibles comme toute autre variable.

Exemple 1. Enregistrer une variable avec $_SESSION.

<?php
session_start
();
// Utilisez $HTTP_SESSION_VARS avec PHP 4.0.6 ou plus ancien
if (!isset($_SESSION['compteur'])) {
    
$_SESSION['compteur'] = 0;
} else {
    
$_SESSION['compteur']++;
}
?>

Exemple 2. Retirer une variable de session avec $_SESSION et register_globals inactif.

<?php
session_start
();
// Utilisez $HTTP_SESSION_VARS avec PHP 4.0.6 ou plus ancien
unset($_SESSION['compteur']);
?>

Attention

N'utilisez PAS la fonction unset() avec $_SESSION sous la forme unset($_SESSION) sinon, cela rendra impossible d'enregistrement de données dans la session en utilisant la super-globale $_SESSION.

Avertissement

Vous ne pouvez pas utiliser les références sur des variables de session car il n'y a aucune manière faisable de restaurer une référence vers une autre variable.

Exemple 3. Retirer une variable de session avec $_SESSION et register_globals activé, après l'avoir enregistré avec $_SESSION.

<?php
session_start
();
// Avec PHP 4.3 et plus récent, vous pouvez simplement utiliser l'exemple précédent
session_unregister('compteur');
?>

Si register_globals est activé, alors toutes les variables globales peuvent être enregistrées comme variables de session, et toutes les variables de sessions seront reconstituées comme variables globales. Comme PHP doit savoir quels variables globales sont enregistrées comme variables de sessions, l'utilisateur doit enregistrer les variables avec session_register() tandis que $HTTP_SESSION_VARS et $_SESSION ne nécessitent pas session_register().

Attention

Avant PHP 4.3, si vous utilisez $_SESSION et que vous avez désactivé register_globals, n'utilisez pas session_register(), session_is_registered() ou session_unregister().

Si vous activez register_globals, session_unregister() doit être utilisé, car les variables de session sont enregistrés comme variables globales lorsque les données de sessions sont relues. Désactiver register_globals est recommandé pour des raisons de sécurité et de performances.

Exemple 4. Enregistrer une variable avec register_globals activé

<?php
if (! isset($_SESSION['compteur'])) {
    
$_SESSION['compteur'] = 1;
} else {
    
$_SESSION['compteur']++;
}
?>

Si register_globals est activé, alors les variables globales et les entrées dans le tableau $_SESSION seront des références sur la même valeur pour les valeurs qui auront été enregistrées avant le démarrage de la session (donc, dans les page précédentes).

De plus, si vous enregistrez une nouvelle variable avec la fonction session_register(), l'entrée dans l'environnement globale et $_SESSION ne fera pas de référence vers la même valeur jusqu'à la prochaine utilisation de session_start() (ceci s'applique à PHP 4.2 est avant seulement). C'est à dire qu'une modification dans les variables globales ne seront pas répercutés dans les entrées de $_SESSION. Il est peu probable que cela ait un impact en pratique, et de plus, cela a été corrigé en PHP 4.3.

Passer l'identifiant de session (session ID)

Il y a deux méthodes de propagation de l'identifiant de session :

  • Cookies

  • Par URL

Le module de session supporte les deux méthodes. Les cookies sont optimaux, mais comme ils ne sont pas sûrs (tous les internautes ne les acceptent pas), ils ne sont pas fiables. La seconde méthode place l'identifiant de session directement dans les URL.

PHP est capable de faire cela de manière transparente, lorsqu'il est compilé avec l'option --enable-trans-sid. Si vous activez cette option, les URL relatives seront modifiées pour contenir l'identifiant de session automatiquement. Alternativement, vous pouvez utiliser la constante SID, qui est définie, si le client n'a pas envoyé le cookie approprié. SID est soit de la forme session_name=session_id ou une chaîne vide.

Note : L'option arg_separator.output de php.ini vous permet de personnaliser le séparateur d'arguments. Pour être complètement en accord avec les spécifications XHTML, spécifiez &amp; ici.

Alternativement, vous pouvez utiliser la constante SID qui est toujours définie. Si le client n'envoie pas un cookie de session approprié, il aura la forme session_name=session_id. Sinon, il vaudra une chaîne vide. Ainsi, vous pouvez dans tous les cas l'inclure dans l'URL.

L'exemple suivant vous montre comment enregistrer une variable et comment réaliser un lien correct avec une autre page, avec SID.

Exemple 5. Compter le nombre de passages d'un utilisateur sur une page

<?php
if (!session_is_registered('compteur')) {
    
session_register('compteur');
    
$compteur = 1;
} else {
    
$compteur++;
}
?>

<p>
Bonjour visiteur, vous avez vu cette page <?php echo $compteur; ?> fois.
</p>

<p>
Pour continuer, <a href="nextpage.php?<?php echo strip_tags(SID); ?>">cliquez ici</a>.
</p>

La fonction strip_tags() est utilisé lors de l'affichage du SID dans le but de contrer les attaques XSS.

L'affichage du SID, comme montré dans l'exemple ci-dessus, n'est pas nécessaire si --enable-trans-sid a été utilisé pour compiler PHP.

Note : Les URL non-relatives sont considérées comme externes au site, et ne recevront pas le SID, car c'est une fuite d'information vers un autre site (envoi d'informations importantes).

Gestion personnalisée des sessions

Pour implémenter un stockage en base de données, ou toute autre méthode, vous aurez besoin de la fonction session_set_save_handler() pour paramétrer vos propres fonctions de stockage.

Table des matières
session_cache_expire -- Retourne la configuration actuelle du cache expire
session_cache_limiter -- Lit et/ou modifie le limiteur de cache de session
session_commit -- Alias de session_write_close()
session_decode -- Décode les données de session
session_destroy -- Détruit une session
session_encode --  Encode les données de session
session_get_cookie_params --  Lit la configuration du cookie de session
session_id -- Lit et/ou modifie l'identifiant courant de session
session_is_registered --  Vérifie si une variable est enregistrée dans la session
session_module_name -- Lit et/ou modifie le module de session courant
session_name -- Lit et/ou modifie le nom de la session
session_regenerate_id --  Remplace l'identifiant de session courant par un nouveau
session_register --  Enregistre une variable dans une session
session_save_path -- Lit et/ou modifie le chemin de sauvegarde des sessions
session_set_cookie_params --  Modifie les paramètres du cookie de session
session_set_save_handler --  Configure les fonctions de stockage de sessions
session_start -- Initialise une session
session_unregister --  Supprime une variable de la session
session_unset --  Détruit toutes les variables d'une session
session_write_close -- Ecrit les données de session et ferme la session