Portail / Sujets autour de la programmation / Programmation C/C++ sous Linux / Serveur d'application avec Qt 6 / Concepts généraux(Sommaire)

Session de travail.

Mise à jour du 12/11/2024.

Nous utilisons le terme "session de travail" car il est plus général que "session de navigation". Une session de navigation est une session de travail opérant au profit d'une application web ce qui sous-tend un utilisateur final qui interagit avec l'application. Or le dialoque avec un serveur d'application peut être provoqué par un automate sans production d'aucune page Web ni présence d'un utilisateur. Il n'en reste pas moins nécessaire d'identifier cet automate tout au long du dialogue.

Intérêts d'une session.

Une session a plusieurs objectifs à la fois fonctionnels et techniques :

  1. Maintenir un marqueur unique qui identifie l'utilisateur final ou l'automate qui a initié la session ;
  2. Maintenir un temporisateur sur la durée d'inactivité de façon à savoir quand purger automatiquement la session ;
  3. Maintenir en mémoire les données nécessaires à la pousuite du dialogue tout au long de la session de travail.

En plus des ces fonctions propres à la session, nous tenons à renforcer la sécurité en offrant un chiffrement à la demande. Toute application Web reçoit à sa création un bi-clef de chiffrement AES 256 bits. Ce bi-clef permet le chiffrement et le déchiffrement de l'identifiant de session qui est transmis à l'UA sous une forme encodée Base64. Ainsi, un attaquant qui capture une session ne peut se servir de cet identfifiant que pendant la durée de vie de l'application.

Pour faire "tourner" la clef de chiffrement des URL et de l'identifiant de session, il suffit d'arrêter et relancer l'application.

En outre, chaque session reçoit à sa création son propre bi-clef de chiffrement AES 256 bits. Les services nécessitant un chiffrement de tout ou partie de leurs données peuvent aussi utiliser ce bi-clef. Notez que la durée de vie des données chiffrées

Notez qu'affecter un identifiant de session unique impose de disposer d'un générateur d'identfiants capable de vérfier si un identifiant a déjà été attribué. Ce besoin n'est en fait pas spécifiques à un serveur d'application aussi a-t-il été décidé d'intégrer ce générateur à la librairie jmp. Cette librairie dispose donc d'une classe singleton appelée UidGeneratorchargée de fournir des identifiants uniques. L'unicité est assurée via la methode contains(quint64 uid) d'un objet dérivé de la classe abstraite IUidVerifier. Cette interface permet "d'externaliser" le contrôle auprès d'un objet qui maintient les UID déjà délivrés. Si l'application ne dispose pas d'un tel objet, la classe par défaut DefaultUidVerfier peut être utilisée.

La question qui se pose ensuite est de savoir à quel niveau conserver les objets de session ? En effet, il est fondamental de pouvoir accéder à une session une fois lu et déchiifré son identifiant. Le besoin d'identification de la session se pose dès que la requête est reçue. C'est donc au niveau du contexte de l'application que doivent être conservées les sessions. Ce contexte contient un dictionnaire de sessions dont les clefs sont les identifiants chiffrés de chaque session. Par la suite, nous identifierons souvent le contexte de l'application à la classe de l'application.

Suivi de session.

L'article de présentation des services expose qu'une session est créée par un service particulier : le service d'accueil de nom réservé home. Une fois que cette session est créée son identifiant est retourné au "client" sous la forme d'un cookie chiffré. Ce cookie est ensuite systématiquement retourné au serveur par le "client" de façon à pouvoir identifier la session.

Si le client retourne de façon automatique le cookie au serveur (si les cookies sont bloquées, l'application ne fonctionnera pas), il n'est est pas de même du serveur. Ce dernier doit systématiquement réémettre le cookie var le client. Cela se fait en ajoutant aux en-têtes HTTP la propriété Set-Cookie.

La classe IService est la classe ancêtre de tout service. Elle impose de coder la méthode setHttpParameters() au niveau de service dérivé. C'est au sein de cette méthode que le cookie de suivi de session doit être ajouté. La classe HttpHelper dispose d'une méthode statique qui facilite la travail si on lui fournit le nom du cookie et son identifiant chiffré avec la clef de l'application et encodé Base64. La classe WebApp propose des méthodes pour faciliter ce chiffrement et encodage.

La classe WebApp est la classe de contexte d'application par défaut. Lors de chaque appel à l'application (méthode process()), cette classe identifie la session et vérfie sa durée d'inactivité. Si cette dernière est supérieure au délai maximum autorisé, la session est supprimée et le service d'accueil est invoqué. Si vous réfinissez cette méthode et que vous utilisez les sessions, il vous faudra reproduire ce mécanisme si cela a du sens pour votre application.

Il existe un cas particulier que vous devez garder à l'esprit : celui où un navigateur revinet avec un identifiant de suivi de session chiffré avant un redémarrage du serveur. En pareil cas, l'identifiant de session ne pourra plus être déchiffré (perte du bi-clef précédent). Si rien n'est fait, la méthode process() de la classe WebApp fera appel au service d'erreur (non réservé error) qui informera le client de la perte de sa session. Il est toutefois possible de déclarer via la configuration de l'application le paramètre sessionLost avec pour valeur le nom du service à invoquer lorsque cette situation est rencontrée. Attention, ce service doit gérer le fait que la session n'existe pas ou que son identfiant n'est pas déchiffrable. Ce service est généralement le service d'accueil. Si le service d'accueil est celui qui impose une connexion à l'application, la page de connexion sera systématiquement émise si l'utilisateur revient apès un délai qui excède la durée maximale d'inactivité autorisée, et ce, quel que soit l'URL invoqué.

Baptême de l'identifiant de session.

Comme le client peut invoquer plusieurs applications du même serveur et même si l'on peut utiliser le même nom de cookie puisque les applications sont sur des "domaines" différents, nous décidons de pouvoir nommer les cookies par un nom fixé par le biais de la configuration (cf. cookieName) bien que ce ne soit pas une obligation. En général il s'agit d'une forme abrégée du nom de l'application (ne doit comporter que des lettres ou des chiffres). Si vous ne définissez pas ce paramètre, l'application utilisera son nom réduit aux 8 premieres lettres et écrites en majuscules. Notez que notre nommage est plus restrictif que la spécification Netscape qui autorise tous les caractères à l'exception de l'espace et de la virgule.

Réalisation d'un prototype.

L'ensemble des ces fonctions sont mises en oeuvre par un objet de classe Session.

Le prototype p45montre comment mettre en oeuvre un objet de cette classe. Voici un exemple de résultat d'exécution :

                     Identifiant de session = 308237005241931049
        Identifiant de session chiffré = W3eplkG1rDLxSPdkYSpqSG01lVI2Qfse43Wy3wGmqC8=
      Identifiant de session déchiffré = 308237005241931049
 Nombre de clefs dans le  dictionnaire = 8
              Sommaire du dictionnaire = \
Clef N° 10801096164144542411 - 1 objets
Clef N° 13717281198718554480 - 1 objets
Clef N° 14519496109583093846 - 4 objets
Clef N° 1462687531119122185 - 4 objets
Clef N° 1530274762963942873 - 10 objets
Clef N° 17353255569070913446 - 1 objets
Clef N° 18088645460963032349 - 3 objets
Clef N° 6402100620394290119 - 7 objets
        Liste des clefs du dictionnaire = \
Clef N° 10801096164144542411
Clef N° 13717281198718554480
Clef N° 14519496109583093846
Clef N° 1462687531119122185
Clef N° 1530274762963942873
Clef N° 17353255569070913446
Clef N° 18088645460963032349
Clef N° 6402100620394290119
Recherche sur la clef (tirage aléatoire) = Clef N° 18088645460963032349
    Premier objet associé à la clef = DataString #-2342208313831489052
Liste des objets associés à la clef [Clef N° 18088645460963032349] \
DataString #-2342208313831489052
DataString #5437076141501298651
6886566444366638373

Rédaction par Jean-Marie Piatte (1983-2021)