# Programmation PHP/Sessions

* Introduction
* Installer PHP
* Composer
* IDE
** PhpStorm
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Commentaires
** Premier programme
** Variables
** Variables superglobales
** Constantes
** Opérateurs
** Fonctions
** Tableaux
** Structures de contrôle
** Boucles
* Programmation avancée
** Dates
** Sessions
** Cookies
** Cache
*** Memcached
*** Redis
** Formulaire
** Fichiers
*** Objets COM
*** Images
** Mails
** Sécurité
** Programmation orientée objet
** Bases de données
*** Microsoft SQL Server
*** MySQL
*** PDO
*** SQLite
** Expressions rationnelles
** Code de haute qualité
*** Analyse statique de programmes
** Exceptions
** Xdebug
** Mots réservés
* Apprendre par l'exemple
** Utilisation de variables
** Un sommaire simple
** Interaction avec un formulaire
** Afficher le résultat d'une requête BDD
** Modifier une table
** Faire un livre d'or
** Faire un mini forum de discussion
** Parser avec DomXml
** Coder en MVC
** Faire un webservice
** Vérification RIO
** AJAX
** Sommaire en Ajax
** Mise à jour périodique d'un cadre
** Mini CMS
** Introduction
** Développement
*** Les couches choisies
*** Code de service
*** Modélisation
*** Implémentation
*** La vue
*** Ajaxification
*** Premier noyau
*** Fournir les données
*** IHM
** Rétrospective
** Conclusion
* Extensions PHP
** cURL
** DOMDocument
** JSON
** MING
** SPL
* Bibliothèques externes
** ADODB
** DOMPDF
** FPDF
** PHPExcel
** PHPMailer
** PHPWord
** RabbitMQ
* Cadriciels
** CakePHP
** PEAR
** Symfony
** Frameworks de tests
*** PHPUnit
*** SimpleTest
*** Behat
* Logiciels métier
* Problèmes connus
* Introduction
* Installer PHP
* Composer
* IDE
** PhpStorm
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Commentaires
** Premier programme
** Variables
** Variables superglobales
** Constantes
** Opérateurs
** Fonctions
** Tableaux
** Structures de contrôle
** Boucles
* Programmation avancée
** Dates
** Sessions
** Cookies
** Cache
*** Memcached
*** Redis
** Formulaire
** Fichiers
*** Objets COM
*** Images
** Mails
** Sécurité
** Programmation orientée objet
** Bases de données
*** Microsoft SQL Server
*** MySQL
*** PDO
*** SQLite
** Expressions rationnelles
** Code de haute qualité
*** Analyse statique de programmes
** Exceptions
** Xdebug
** Mots réservés
* Apprendre par l'exemple
** Utilisation de variables
** Un sommaire simple
** Interaction avec un formulaire
** Afficher le résultat d'une requête BDD
** Modifier une table
** Faire un livre d'or
** Faire un mini forum de discussion
** Parser avec DomXml
** Coder en MVC
** Faire un webservice
** Vérification RIO
** AJAX
** Sommaire en Ajax
** Mise à jour périodique d'un cadre
** Mini CMS
** Introduction
** Développement
*** Les couches choisies
*** Code de service
*** Modélisation
*** Implémentation
*** La vue
*** Ajaxification
*** Premier noyau
*** Fournir les données
*** IHM
** Rétrospective
** Conclusion
* Extensions PHP
** cURL
** DOMDocument
** JSON
** MING
** SPL
* Bibliothèques externes
** ADODB
** DOMPDF
** FPDF
** PHPExcel
** PHPMailer
** PHPWord
** RabbitMQ
* Cadriciels
** CakePHP
** PEAR
** Symfony
** Frameworks de tests
*** PHPUnit
*** SimpleTest
*** Behat
* Logiciels métier
* Problèmes connus
[ Modifier le sommaire ]
Consultez également ces pages dans d’autres projets Wikimedia :
* Article encyclopédique sur Wikipédia.
* Définition sur Wiktionnaire.
Comme vous le savez, à la fin d'un script PHP, toutes les variables créées sont détruites et il est impossible d'y accéder depuis un autre script. Alors comment faire pour passer des données entre les pages ?
La réponse : les sessions.
C'est en effet la solution la plus simple pour un webmaster afin de garder des informations sur son visiteur.

## Un cookie et une session, quelles différences

Une session est plus ou moins semblable aux cookies HTTP. Les données d'une session sont cependant stockées sur le serveur et non chez le client, ce qui l'empêche de pouvoir les modifier manuellement, comme il peut le faire pour un cookie.

## La durée de vie d'une session

Une session est, comme son nom l'indique, une session de navigation. Elle commence donc lors de l'accès à une page les utilisant et se termine à la fermeture du navigateur du client.
Une fois la session terminée, elle est détruite ainsi que toutes les données qu'elle contient. Elle doit donc ne contenir que des données temporaires.
Cependant, la session possède aussi un délai d'expiration. Celui-ci peut être modifié dans la configuration du serveur (directive session.gc_maxlifetime de php.ini), mais vaut généralement une trentaine de minutes. Une fois ce délai dépassé, la session est supprimée.

## Comment ça marche ?

Lors de l'accès à une page nécessitant une session, PHP va vérifier si une a déjà été ouverte et la réutiliser ou en créer une nouvelle. Il va donc lui attribuer un identifiant unique et se débrouiller pour que la prochaine page consultée puisse le connaître.
Pour cela, il exploite deux fonctionnalités. Premièrement, si l'utilisation de cookie est possible (le client ne les a pas désactivés), PHP crée un cookie contenant l'identifiant de session. Deuxièmement, si les cookies ne sont pas disponibles, il va réécrire les URL de la page pour inclure cet identifiant dans le lien.
Dans les deux cas, le script ayant besoin d'accéder aux données de la session recevra l'identifiant et sera capable de charger les données qu'elle contient.

## Est-ce que c’est sécurisé

Une session est toujours plus sécurisée qu'un cookie puisque le client ne peut pas la modifier manuellement. Un risque subsiste tout de même si l'identifiant de session peut être découvert.
Par exemple, les cookies transitent sur le réseau en clair. Si quelqu’un est capable d'intercepter les communications entre le client et le serveur, il est capable de voir le cookie et de découvrir l'identifiant de session. Il n'aura alors plus qu’à créer un faux cookie et PHP le prendra pour le pauvre internaute s'étant fait voler son cookie. Pour éviter cela, on peut utiliser une connexion cryptée ou configurer le serveur de façon à ce qu’il rende la lecture de ce cookie impossible par JavaScript (Http Only).

## Utiliser les sessions
### Initialiser une session

Pour pouvoir utiliser la fonctionnalité de session de PHP, il faut lancer le moteur de session en utilisant la fonction session_start.
Cette fonction doit être en mesure d'envoyer des headers HTTP, aucune donnée ne doit donc avoir été transmise au navigateur. Vous pouvez soit placer ce code au tout début de votre script, soit utiliser les fonctions de bufférisation de sortie.

#### Une session portant un nom personnalisé

Une session porte par défaut le nom "PHPSESSID", c’est lui qui sera utilisé comme nom de cookie ou comme paramètre GET dans les liens... pas très esthétique. Il peut donc vous venir l'envie de changer ce nom.
Pour cela, la fonction session_name entre en scène.
Ce code va donc charger une session avec l'identifiant provenant du cookie ou du paramètre GET portant le nom nom_de_session.
Noter la position de l'instruction 'session_start'. Elle doit se trouver AVANT n’importe quel traitement de votre page '.php' .

#### Changer manuellement l'identifiant de la session

PHP détecte automatiquement l'identifiant à utiliser, cependant, vous pourrez avoir besoin de le changer manuellement, si vous voulez développer un système alternatif pour passer l'identifiant de session entre les pages. Vous pouvez par exemple vous baser sur le hachage (md5 ou sha1) de l'adresse IP du client pour déterminer l'identifiant de la session. Attention aux proxys et aux internautes dont l'IP change à chaque requête.
Pour définir manuellement l'identifiant de session, la fonction session_id. Elle prend un paramètre optionnel, qui est le nouvel identifiant de session. Dans tous les cas, la fonction retourne l'identifiant courant de la session.
* Exemple
* <?php
* $identifiant = sha1($_SERVER['REMOTE_ADDR']);
* /* Premièrement, nous récupérons l'adresse IP du client,
* puis nous utilisons une fonction de hachage pour
* générer un code valide. En effet, l'identifiant d'une
* session ne peut contenir que des lettres (majuscules
* ou minuscules) et des chiffres. */
* $ancien_identifiant = session_id($identifiant);
* /* Ensuite, nous modifions manuellement l'identifiant de
* session en utilisant session_id et en lui donnant
* l'identifiant généré plus haut. Comme toujours, la
* fonction retourne l'ancien identifiant, on le place
* dans une variable, au cas où on aurait besoin de le
* réutiliser. */
* session_start;
* /* On démarre la session, PHP va utiliser le nouvel
* identifiant qu'on lui aura fournis. */
Dans l'exemple ci-dessus, deux ordinateurs accédant au site par la même adresse IP publique, auront accès à la dernière session ouverte (donc pas forcément la leur).

### Lire et écrire des données dans la session

Les données de la session sont très facilement accessibles au travers d'un simple tableau PHP. Depuis PHP 4.1.0, vous pouvez utiliser le tableau super-global $_SESSION. Dans les versions plus anciennes, il s'appelait $HTTP_SESSION_VARS et nécessitait le mot clé global pour y accéder depuis une fonction.
Ces tableaux n'existent qu'une fois la session chargée. Tout ce qui est stocké à l'intérieur est sauvegardé et accessible depuis toutes les pages PHP utilisant les sessions.

#### Exercice : Une zone d'administration protégée par mot de passe

Dans cet exercice, nous allons fabriquer pas-à-pas une zone d'administration pour votre site web, protégée par un mot de passe. Nous nous occuperons de la partie identification uniquement.
Dans le chapitre précédent, vous avez également créé le même type de script, mais en utilisant un cookie. Nous allons donc adapter le code en utilisant des sessions à la place.

##### Le formulaire

Voici le code du formulaire en HTML, il va afficher une boîte de texte et un bouton "Connexion".

##### La page de vérification

Le formulaire ci-dessus pointe vers une page nommée verification.php. Cette page va vérifier que le mot de passe est juste et, si c’est le cas, placer un élément dans le tableau de la session pour que la page suivante puisse vérifier que vous êtes bien autorisé à voir la page.
Premièrement, nous devons initialiser la session. Nous laissons PHP choisir le nom.
L'appel à la fonction session_start a fabriqué le tableau $_SESSION. Pour l'instant celui-ci est vide.
Il faut maintenant vérifier que le mot de passe fourni est le bon. Nous créons ensuite une entrée dans le tableau de la session contenant true (vrai) si le code est le bon. Nous pouvons alors rediriger le navigateur de l'internaute ou afficher un message d'erreur.
Si vous ne comprenez pas la ligne if ($mdp == $_POST['mdp']) {, vous devriez lire (ou relire) le chapitre sur les formulaires.
Pour résumé, le code suivant suffit à l'identification du visiteur :

##### La page d'administration

Cette page doit se nommer admin.php. Si vous décidez d’utiliser un autre nom, il faudra modifier le script d'identification pour qu’il pointe sur la bonne page.
Comme dans l'autre page, nous devons commencer par initier une session.
Nous avons alors accès au tableau $_SESSION.
Si le visiteur a fourni le bon mot de passe, il existe un élément dans le tableau nommé 'admin' et valant true. Dans le cas contraire, cet élément n'existe pas. Il suffit donc de vérifier sa présence pour savoir si le visiteur est réellement l'administrateur du site. Pour cela, nous utilisons la fonction isset qui vérifie si la variable (ou l'élément du tableau) existe.
La suite du script n'est plus le sujet de cet exercice, le but est en effet atteint. Vérifier l'identité du visiteur pour lui permettre d'accéder à un espace privé.
La bonne pratique en terme de sécurité, pour éviter que des attaques puissent énumérer les utilisateurs (avant de chercher leurs mots de passe), et de renvoyer la même erreur 403 si l'utilisateur n'existe pas, ou s'il existe mais que son mot de passe est incorrect.

### Fermer une session

De la même façon que d'autre fonctionnalités de PHP, comme les connexions aux bases de données ou un pointeur de fichier, les sessions n'ont pas besoin d’être fermée.
Une fois le script PHP terminé, les données de la session sont automatiquement sauvegardées pour le prochain script.
Cependant, durant toute l'exécution du script, le fichier de la session est verrouillé et aucun autre script ne peut y toucher. Ils doivent donc attendre que le premier arrive à la fin.
Vous pouvez fermer plus rapidement une session en utilisant la fonction session_write_close.
Si vous voulez également détruire la session, vous pouvez utiliser la fonction session_destroy couplée à la fonction session_unset.