Sessions

HTTP est un protocole sans état, mais presque toutes les applications ont besoin de conserver un état entre les requêtes, par exemple le contenu d'un panier d'achat. C'est à cela que sert une session. Voyons maintenant

  • comment utiliser les sessions
  • comment éviter les conflits de noms
  • comment définir l'expiration

Lors de l'utilisation de sessions, chaque utilisateur reçoit un identifiant unique appelé ID de session, qui est transmis dans un cookie. Cet identifiant sert de clé pour les données de session. Contrairement aux cookies, qui sont stockés du côté du navigateur, les données de session sont stockées du côté du serveur.

On configure la session dans la configuration, le choix du temps d'expiration est important.

La session est gérée par l'objet Nette\Http\Session, que vous obtenez en le passant en utilisant l'injection de dépendances. Dans les présentateurs, il suffit d'appeler $session = $this->getSession().

Installation et configuration requise

Démarrage de la session

Par défaut, Nette démarre automatiquement une session au moment où nous commençons à lire ou à écrire des données dans celle-ci. Pour démarrer manuellement une session, utilisez $session->start().

PHP envoie des en-têtes HTTP affectant la mise en cache lors du démarrage de la session, voir session_cache_limiter, et éventuellement un cookie avec l'ID de la session. Par conséquent, il est toujours nécessaire de démarrer la session avant d'envoyer des données au navigateur, sinon une exception sera levée. Donc, si vous savez qu'une session sera utilisée pendant le rendu de la page, lancez-la manuellement avant, par exemple dans le présentateur.

En mode développeur, Tracy démarre la session car il l'utilise pour afficher les barres de redirection et de demandes AJAX dans la barre Tracy.

Section

En PHP pur, le stockage des données de session est implémenté comme un tableau accessible via une variable globale $_SESSION. Le problème est que les applications sont normalement constituées d'un certain nombre de parties indépendantes, et si toutes n'ont qu'un seul et même tableau disponible, tôt ou tard, une collision de noms se produira.

Nette Framework résout le problème en divisant l'espace entier en sections (objets Nette\Http\SessionSection). Chaque unité utilise alors sa propre section avec un nom unique et aucune collision ne peut se produire.

Nous obtenons la section à partir du gestionnaire de session :

$section = $session->getSection('unique name');

Dans le présentateur il suffit d'appeler getSession() avec le paramètre :

// $this est le présentateur
$section = $this->getSession('unique name');

L'existence de la section peut être vérifiée par la méthode $session->hasSection('unique name').

La section elle-même est très facile à utiliser avec les méthodes set(), get() et remove():

// écriture de variables
$section->set('userName', 'franta');

// lecture d'une variable, renvoie null si elle n'existe pas
echo $section->get('userName');

// suppression d'une variable
$section->remove('userName');

Il est possible d'utiliser le cycle foreach pour obtenir toutes les variables de la section :

foreach ($section as $key => $val) {
	echo "$key = $val";
}

Comment définir l'expiration

L'expiration peut être définie pour des sections individuelles ou même des variables individuelles. Nous pouvons laisser la connexion de l'utilisateur expirer au bout de 20 minutes, tout en conservant en mémoire le contenu d'un panier d'achat.

// la section expirera après 20 minutes
$section->setExpiration('20 minutes');

Le troisième paramètre de la méthode set() est utilisé pour définir l'expiration des variables individuelles :

// la variable 'flash' expire après 30 secondes
$section->set('flash', $message, '30 seconds');

N'oubliez pas que le temps d'expiration de l'ensemble de la session (voir la configuration de la session) doit être égal ou supérieur au temps défini pour les sections ou les variables individuelles.

L'annulation de l'expiration précédemment définie peut être obtenue par la méthode removeExpiration(). La suppression immédiate de la section entière sera assurée par la méthode remove().

Événements $onStart, $onBeforeWrite

L'objet Nette\Http\Session possède les événements $onStart et $onBeforeWrite, ce qui vous permet d'ajouter des rappels qui sont appelés après le démarrage de la session ou avant qu'elle ne soit écrite sur le disque puis terminée.

$session->onBeforeWrite[] = function () {
	// écrit les données dans la session
	$this->section->set('basket', $this->basket);
};

Gestion des sessions

Aperçu des méthodes de la classe Nette\Http\Session pour la gestion des sessions :

start(): void

Démarre une session.

isStarted(): bool

La session est-elle lancée ?

close(): void

Termine la session. La session se termine automatiquement à la fin du script.

destroy(): void

Termine et supprime la session.

exists(): bool

La requête HTTP contient-elle un cookie avec un ID de session ?

regenerateId(): void

Génère un nouvel ID de session aléatoire. Les données restent inchangées.

getId(): string

Renvoie l'ID de la session.

Configuration

Nous configurons la session dans la configuration. Si vous écrivez une application qui n'utilise pas de conteneur DI, utilisez ces méthodes pour la configurer. Elles doivent être appelées avant le démarrage de la session.

setName(string $name): static

Définit le nom du cookie qui est utilisé pour transmettre l'ID de session. Le nom par défaut est PHPSESSID. Ceci est utile si vous exécutez plusieurs applications différentes sur le même site.

getName(): string

Renvoie le nom du cookie de session.

setOptions(array $options)static

Configure la session. Il est possible de définir toutes les directives de session PHP (en format camelCase, par exemple écrire savePath au lieu de session.save_path) et aussi readAndClose.

setExpiration(?string $time)static

Définit le temps d'inactivité après lequel la session expire.

setCookieParameters(string $path, string $domain=null, bool $secure=null, string $samesite=null)static

Définit les paramètres des cookies. Vous pouvez modifier les valeurs par défaut des paramètres dans configuration.

setSavePath(string $path)static

Définit le répertoire dans lequel les fichiers de session sont stockés.

setHandler(\SessionHandlerInterface $handler)static

Définit le gestionnaire personnalisé, voir la documentation PHP.

Sécurité d'abord

Le serveur suppose qu'il communique avec le même utilisateur tant que les demandes contiennent le même identifiant de session. La tâche des mécanismes de sécurité est de garantir que ce comportement fonctionne réellement et qu'il n'existe aucune possibilité de substituer ou de voler un identifiant.

C'est pourquoi Nette Framework configure correctement les directives PHP pour transférer l'identifiant de session uniquement dans les cookies, pour éviter l'accès depuis JavaScript et pour ignorer les identifiants dans l'URL. De plus, dans les moments critiques, comme la connexion de l'utilisateur, il génère un nouvel identifiant de session.

La fonction ini_set est utilisée pour configurer PHP, mais malheureusement, son utilisation est interdite chez certains hébergeurs. Si c'est votre cas, essayez de demander à votre hébergeur d'autoriser cette fonction pour vous, ou au moins de configurer son serveur correctement.

version: 4.0