web-dev-qa-db-fra.com

Comment garder les applications sans état

C'est peut-être une question compliquée, mais j'essaie de mieux comprendre l'apatridie.

D'après ce que j'ai lu, les applications Web devraient être sans état, ce qui signifie que chaque demande est traitée comme une transaction indépendante. En conséquence, la session et les cookies doivent être évités (car les deux sont avec état). Une meilleure approche consiste à utiliser des jetons, qui sont sans état car rien n'est stocké sur le serveur.

J'essaie donc de comprendre comment les applications Web peuvent être apatrides lorsqu'il y a des données qui sont conservées pour ma session (comme des articles dans un panier)? Sont-ils réellement stockés dans une base de données quelque part puis périodiquement purgés? Comment cela fonctionne-t-il lorsque vous utilisez un jeton au lieu de cookies?

Et puis, comme question connexe, les principaux sites Web (Amazon, Google, Facebook, Twitter, etc.) sont-ils réellement apatrides? Utilisent-ils des jetons ou des cookies (ou les deux)?

100
user253058

"les applications web doivent être sans état" doit être compris comme "les applications web doivent être sans état sauf s'il existe une très bonne raison d'avoir un état". Un "panier" est une caractéristique dynamique de par sa conception, et le nier est tout à fait contre-productif. L'intérêt du modèle de panier d'achat est de préserver l'état de l'application entre les demandes.

Une alternative que je pourrais imaginer comme un site Web sans état qui implémente un panier serait une application d'une seule page qui garde le panier complètement côté client, récupère les informations produit avec AJAX appelle et l'envoie ensuite au serveur en même temps lorsque l'utilisateur effectue un paiement. Mais je doute que j'aie jamais vu quelqu'un le faire, car cela ne permet pas à l'utilisateur d'utiliser plusieurs onglets de navigateur et ne le fait pas ' t conserver l'état quand ils ferment accidentellement l'onglet. Bien sûr, il existe des solutions de contournement comme l'utilisation de localstorage, mais vous avez à nouveau l'état, juste sur le client plutôt que sur le serveur.

Chaque fois que vous avez une application Web qui nécessite de conserver les données entre les pages vues, vous le faites généralement en introduisant des sessions. La session à laquelle appartient une demande peut être identifiée par un cookie ou par un paramètre d'URL que vous ajoutez à chaque lien. Les cookies doivent être préférés car ils gardent vos URL plus pratiques et empêchent votre utilisateur de partager accidentellement une URL avec son identifiant de session. Mais avoir des jetons URL comme solution de rechange est également vital pour les utilisateurs qui désactivent les cookies. La plupart des frameworks de développement Web ont un système de gestion de session qui peut le faire dès le départ.

Côté serveur, les informations de session sont généralement stockées dans une base de données. La mise en cache en mémoire côté serveur est facultative. Il peut considérablement améliorer le temps de réponse, mais ne vous permettra pas de transférer des sessions entre différents serveurs. Vous aurez donc besoin d'une base de données persistante comme solution de rechange.

les principaux sites Web (Amazon, Google, Facebook, Twitter, etc.) sont-ils réellement apatrides? Utilisent-ils des jetons ou des cookies (ou les deux)?

Vous permettent-ils de vous connecter? Lorsque vous fermez ensuite l'onglet et revisitez le site, êtes-vous toujours connecté? Si vous l'êtes, ils utilisent des cookies pour préserver votre identité entre les sessions.

97
Philipp

Il est vrai que les applications Web doivent être sans état. Cependant, les variables de session, les cookies et les jetons ne violent pas cela lorsqu'ils sont tous stockés sur le client (navigateur Web). Ils peuvent être des paramètres dans la demande.

Voici un modèle simplifié:

Web Browser (has state) <-> Web Server (stateless) <-> Database (has state)

Cela pourrait fonctionner pour Software Engineering Stack Exchange. Cette réponse que je tape fait partie de l'état de mon navigateur Web. Tant que c'est le seul endroit où il se trouve, il n'est accessible à personne d'autre qu'à moi. Mais dès que je frappe Post your Answer mon navigateur l'envoie au serveur Web. Le serveur Web traite la publication sans utiliser son propre état. Il apprend qui je suis à partir de mon navigateur et de la base de données. Une fois qu'il a terminé de vérifier ma publication et de l'ajouter à la base de données, le serveur Web oublie rapidement mes informations.

Voilà ce que signifie apatride. Le serveur n'est pas responsable de se souvenir de tout cela. Ce n'est pas son travail.

Cela présente de nombreux avantages. Si le serveur Web a une fuite de mémoire, il est détectable car son empreinte mémoire ne devrait pas augmenter. Si le serveur Web tombe en panne, mon identité ne va pas avec. Si quelqu'un essaie de faire une attaque par déni de service, il ne peut pas utiliser les ressources d'état du serveur Web pour le faire, car le serveur Web ne lui alloue aucun état entre les sessions. Tout cela vise à rendre le serveur Web stable. De cette façon, quand il commence à fonctionner, il continue à fonctionner.

Maintenant, bien sûr, je consomme des ressources dans la base de données, mais ces ressources ont d'abord été vérifiées par rapport à mon allocation par quelque chose de stable sur lequel nous pouvons compter pour protéger la base de données du Web sauvage et laineux: le serveur Web sans état et d'application des règles commerciales.

59
candied_orange

les applications Web doivent être apatrides

Non-sens. Les requêtes Web doivent être sans état. Ou plus précisément, les demandes Web sont sans état.

Mais dire qu'une application entière devrait être sans état est un non-sens complet.

chaque demande est traitée comme une transaction indépendante.

Oui, exactement . Ou plus précisément, oui, nécessairement . Sur HTTP, chaque requête est intrinsèquement indépendante de toutes les autres requêtes. L'ajout d '"état" à HTTP nécessite que vous identifiez, stockez et récupérez explicitement "état" pour chaque demande "avec état". Et cela demande des efforts, diminue les performances et ajoute de la complexité.

Et, pour ces raisons, chaque demande qui peut être sans état "devrait" être sans état.

En conséquence, la session et les cookies doivent être évités (car les deux sont avec état). Une meilleure approche consiste à utiliser des jetons

Quelques éléments: les jetons peuvent également être liés au stockage de session. Les cookies n'ont pas besoin d'être liés au stockage de session. Les jetons sont souvent stockés dans des cookies. Et, parfois, une session est simplement le bon outil pour le travail.

Cela signifie qu'au moins parfois , les sessions et les cookies sont tout aussi "meilleurs" que les jetons!

[Les jetons] sont sans état car rien n'est stocké sur le serveur.

Eh bien c'est ça. C'est ce qu'est vraiment le dogme de "l'apatridie". Bien, pour être clair, il ne s'agit pas de stocker "rien" sur le serveur, il ne s'agit pas de stocker l'état de session sur le serveur.

Ma boîte de réception Gmail est par exemple en état. Et ça sacrément bien mieux être stocké sur le serveur! Mais ce n'est pas l'état de la session .

Donc, au lieu d'avoir des serveurs qui peuvent prendre un petit identifiant et comprendre qui vous êtes et ainsi de suite, les applications sans état veulent se rappeler qui vous êtes et ce que vous faites chaque sanglant L'état de l'application existe toujours, le client est juste responsable de le conserver.

Maintenant, si cet état est petit, c'est probablement OK. Dans certains cas, c'est très bon.

Et puis, bien sûr, il y a des choses que nous attendons simplement avec état ...

comment les applications Web peuvent-elles être apatrides lorsqu'il y a des données qui sont conservées pour ma session (comme des articles dans un panier)? Sont-ils réellement stockés dans une base de données quelque part puis périodiquement purgés?

Deux options. Soit vous avez une session, soit vous êtes dans le déni!

... Mais sérieusement. Vous ne stockeriez pas normalement un panier dans un cookie. Quelque chose comme un panier sera soit stocké dans une session "traditionnelle", soit il sera stocké en tant qu'objet Cart, avec une sorte d'ID que le serveur utilise pour le tirer dans les requêtes suivantes. Un peu comme une .. euh ... ... euh ... session.

Pour de vrai, sérieusement: il y a un grand degré auquel "état" est exactement ce que nous appelons quand deux agents communicants peuvent contextualiser les messages dans une conversation. Et une session, traditionnellement comprise, est exactement ce que nous appelons généralement le mécanisme par lequel cela se produit.

Je dirais que, que vous utilisiez des jetons ou des "sessions" pour chaque demande que votre serveur gère, vous devez soit contextualiser cette demande pour la satisfaire , soit vous ne le faites pas. Si le contexte n'est pas nécessaire, ne le récupérez pas. Si le contexte est nécessaire, vous feriez mieux de l'avoir à proximité!

Et puis, comme question connexe, les principaux sites Web (Amazon, Google, Facebook, Twitter, etc.) sont-ils réellement apatrides? Utilisent-ils des jetons ou des cookies (ou les deux)?

Probablement les deux. Mais, en règle générale, ils font exactement ce que vous faites: ils définissent des cookies pour identifier les enregistrements "d'état" dans des bases de données massives "de session".

Lorsque cela est possible, je soupçonne qu'ils poussent les revendications d'identité de base dans des "jetons" de courte durée pour éviter les conflits inutiles sur le stockage centralisé. Mais, le fait que beaucoup de ces services me permettent de "me déconnecter de tous les autres emplacements" est un bon indicateur que, s'ils utilisent des jetons, ils sont au moins "pris en charge" par un modèle de session semi-traditionnel .

30
svidgen

L'état n'est pas nécessairement une mauvaise chose, mais vous devez comprendre la différence entre les applications avec état et sans état. En bref, les applications avec état conservent des informations sur la session en cours, contrairement aux applications sans état. Les informations stockées en permanence dans le cadre d'un compte utilisateur peuvent ou non être stockées dans une session, mais le stockage d'informations liées à un compte utilisateur ne rend pas en soi l'application avec état. L'état de conservation requiert que le serveur conserve les informations sur la session de l'utilisateur actuel au-delà de ce que le navigateur client gère. Par exemple, un client peut s'authentifier et recevoir un cookie JSESSIONID, qu'il envoie ensuite au serveur à chaque demande. Si le serveur commence à stocker des éléments dans la portée de session de l'application en fonction de ce JSESSIONID, il devient avec état.

Apatridie

Par sans état, nous voulons dire que le serveur et le client ne conservent pas les informations actuelles sur la session utilisateur. Le client et le serveur peuvent utiliser une certaine forme de jeton pour assurer l'authentification entre les demandes, mais aucune autre information actuelle n'est stockée. Un cas d'utilisation typique d'une telle solution pourrait être un site d'actualités où la plupart des utilisateurs (nouveaux consommateurs) consomment des informations mais ne produisent pas d'informations qui retournent sur le site. Dans de tels cas, le site n'a pas besoin de conserver des informations sur la session utilisateur en cours. Notez que le site peut toujours utiliser des cookies pour identifier l'utilisateur et stocker des informations sur l'utilisation de ce site par cet utilisateur, mais cela peut toujours être considéré comme apatride car tout ce qui est enregistré peut être transactionnel, par exemple lien sur lequel l'utilisateur a cliqué, qui peut être enregistré par le serveur, mais non conservé dans une session utilisateur.

état sur le serveur

Sur le serveur, une application avec état enregistre les informations d'état sur les utilisateurs actuels. Cette approche implique généralement l'utilisation de cookies pour identifier le système de l'utilisateur afin que l'état puisse être maintenu sur le serveur entre les requêtes. Les sessions peuvent ou non être authentifiées, selon le contexte de l'application. Les applications de serveur avec état offrent l'avantage de mettre en cache les informations sur l'état des utilisateurs sur le serveur, accélérant ainsi les recherches et le temps de réponse des pages. En revanche, le stockage d'informations dans la portée de la session est coûteux et à grande échelle, il devient très gourmand en ressources. Il crée également un vecteur d'attaque potentiel pour que les pirates essaient de détourner les identifiants de session et de voler les sessions utilisateur. Les applications de serveur avec état ont également le défi de protéger les sessions utilisateur contre les interruptions de service inattendues, par ex. une panne de serveur. Une solution courante à ce problème consiste à regrouper les sessions sur un cluster de machines serveur, mais là encore, à grande échelle, il devient rapidement impossible de regrouper toutes les sessions sur toutes les machines.

Statefulness sur le client

En utilisant JavaScript et des technologies de navigateur modernes comme sessionStorage, l'application peut désormais facilement stocker des informations d'état sur une session utilisateur sur l'appareil de cet utilisateur. Dans l'ensemble, l'application peut toujours être considérée comme avec état, mais le travail de maintien de l'état a été déplacé vers le client. Cette approche présente un gros avantage (pour le mainteneur de l'application Web) sur le maintien de l'état sur le serveur en ce que chaque utilisateur maintient, en fait, son propre état, et il n'y a pas de charge sur l'infrastructure du serveur. À l'échelle du Web, ce type de choix architectural a d'énormes répercussions sur les coûts de matériel et d'électricité. Cela pourrait littéralement coûter des millions de dollars par an pour maintenir l'état du serveur. Passer à un système maintenant l'état du client pourrait alors permettre d'économiser des millions de dollars par an.

Jetons contre cookies

Les cookies servent d'identifiants pour les appareils/navigateurs clients. Ils peuvent être utilisés pour stocker toutes sortes de choses, mais généralement ils stockent une certaine forme d'identifiant, comme CFID/CFTOKEN dans les applications CFML. Les cookies peuvent être configurés pour vivre dans le navigateur de l'utilisateur pendant une longue période, ce qui permet de faire des choses comme maintenir l'authentification sur une application entre les sessions du navigateur. Les cookies peuvent également être définis sur la mémoire uniquement afin qu'ils expirent lorsqu'un utilisateur ferme le navigateur.

Les jetons sont généralement des informations d'identification sur l'utilisateur qui sont générées sur le serveur (à l'aide du chiffrement pour brouiller les informations), transmises au client et renvoyées au serveur avec la demande suivante. Ils peuvent être passés dans l'en-tête de la demande et de la réponse, ce qui est un modèle courant dans les applications d'une seule page. Idéalement, chaque demande/réponse entraîne la génération d'un nouveau jeton, de sorte que les jetons ne peuvent pas être interceptés et utilisés plus tard par un attaquant.

Applications à page unique et état du client

Avec les SPA, les informations d'état sont chargées dans le navigateur client et y sont conservées. Lorsque l'état change, par ex. vous publiez une mise à jour sur votre compte de réseau social, le client relaie cette nouvelle transaction au serveur. Dans ce cas, le serveur enregistre cette mise à jour dans un magasin de données persistantes comme une base de données et relaie toutes les informations au client dont il a besoin pour se synchroniser avec le serveur en fonction de la mise à jour (par exemple, un ID pour la mise à jour).

Notez que ce modèle de stockage de l'état sur le client offre des avantages pour les expériences en ligne/hors ligne dans la mesure où vous pouvez être déconnecté du serveur tout en ayant une application quelque peu utilisable. Twitter est un bon exemple de ce cas, où vous pouvez consulter tout ce qui est chargé côté client dans votre flux Twitter même si vous êtes déconnecté de l'application serveur Twitter. Ce modèle crée également une complexité dans la synchronisation entre le serveur et le client, qui est un sujet à part entière. Les complexités de la solution sont un compromis pour pouvoir maintenir l'état sur le client.

L'état du client fait que les applications Web se sentent et se comportent plus comme des applications de bureau traditionnelles. Contrairement aux applications de bureau, vous n'aurez généralement pas toutes les informations de votre compte chargées dans votre session client dans un navigateur. Dans de nombreux cas, cela serait impraticable et entraînerait de mauvaises expériences. Pouvez-vous imaginer essayer de charger une boîte Gmail entière dans le navigateur? Au lieu de cela, le client conserve des informations telles que l'étiquette/le dossier que vous regardez et où dans la liste des e-mails dans ce dossier que vous regardez. Équilibrer les informations d'état à maintenir et celles à demander selon les besoins est un autre défi technique de ce modèle, et encore une fois, il représente un compromis entre l'aspect pratique et la fourniture de bonnes expériences utilisateur.

paniers d'achat et similaires

Quant aux spécificités comme les paniers d'achat, cela dépend vraiment de la solution. Un panier d'achat peut être stocké dans une base de données sur le serveur, il peut être stocké uniquement dans la portée de la session sur le serveur, ou il peut même être stocké dans le client. Amazon a des paniers d'achat persistants pour les utilisateurs connectés et des paniers "temporaires" pour les utilisateurs anonymes, bien que ces paniers soient persistants dans une certaine mesure.

Lorsque vous parlez de quelque chose comme Google, qui est vraiment un tas d'applications différentes vivant sous la même marque, elles ne partagent probablement pas une architecture commune, et chacune est conçue de la manière qui répond le mieux aux besoins de ses utilisateurs. Si vous voulez savoir comment un site est construit, ouvrez les outils de développement dans votre navigateur et regardez-le. Recherchez les cookies, surveillez le trafic réseau et voyez comment il fonctionne.

Désolé si cette réponse divulgue un peu, mais l'état d'esprit est un sujet complexe.

16
Robert Munn

Les sessions et les cookies ne doivent pas être évités. Vous pouvez toujours les avoir avec des applications Web sans état.

Il y a une grande différence entre Java et Ruby on Rails. Java stockent la session en mémoire à l'aide d'une session) clé stockée dans un cookie. Ceci est rapide pour récupérer l'état de l'utilisateur et le panier. Cependant, vous devez toujours toucher le même serveur avec votre session.

Les applications Rails stockent l'ID utilisateur dans un cookie signé et crypté. Il ne peut pas être modifié. Lorsque vous chargez une page, l'application Web récupère votre état, votre utilisateur et votre panier dans une base de données. C'est plus lent, mais la clé est, vous pouvez frapper n'importe quelle instance! Cela vous permet de redémarrer, de mettre à l'échelle et d'arrêter les instances à volonté. Très pratique. Il peut également être accéléré avec une base de données de cache partagée en mémoire comme Redis. Ou vous pouvez stocker le panier dans le cookie, à condition qu'il soit assez petit.

Ainsi, vous pouvez atteindre l'apatridie, grâce à des techniques intelligentes, et ajouter la capacité de s'adapter à volonté.

6
Chloe

Lorsqu'il s'agit d'apatrides - par ex. dans un service HTTP RESTful - il s'agit d'éviter de stocker l'état du côté serveur. Au mieux, cela inclut également d'éviter de stocker un état dans une base de données ou d'autres stockages persistants sur le backend. Pour être clair, je parle d'un état et non de données en général. Il semble que certains gars mélangent les choses.

Une communication sans état présente plusieurs avantages, notamment en termes d'évolutivité et de disponibilité.

Une meilleure approche consiste à utiliser des jetons, qui sont sans état car rien n'est stocké sur le serveur.

C'est vrai (pour certains protocoles d'authentification et d'autorisation). Les jetons peuvent (mais pas en soi) fournir toutes les informations dans la demande qui sont nécessaires pour authentifier un utilisateur ou autoriser une action. Pour un exemple, jetez un œil à JWT .

J'essaie donc de comprendre, comment les applications Web peuvent-elles être apatrides lorsqu'il y a des données qui sont conservées pour ma session (comme des articles dans un panier)? Sont-ils réellement stockés dans une base de données quelque part puis périodiquement purgés? Comment cela fonctionne-t-il lorsque vous utilisez un jeton au lieu de cookies?

Concernant l'exemple du panier. Ce n'est pas un problème de stocker tous les articles du panier côté client sans utiliser de session ou de cookies. Vous pouvez trouver un exemple sur smashingmagazine.com . Mais il est également possible de réaliser un panier d'achat apatride avec des cookies (au moins si votre assortiment n'est pas si grand et que 4 Ko de stockage vous suffisent).

Ne vous méprenez pas, cela ne signifie pas que vous devez mettre en place un panier sans état à tout prix. Amazon ou d'autres grandes plates-formes d'achat en ligne utilisent des implémentations de panier d'achat dynamiques, car l'expérience utilisateur et la convivialité sont plus importantes pour eux que de répondre à des exigences techniques non fonctionnelles telles que l'évolutivité.

En règle générale, les jetons ne sont pas utilisés pour stocker des informations telles que les articles du panier. Ils sont utilisés pour une authentification et une autorisation sans état.

Et puis, comme question connexe, les principaux sites Web (Amazon, Google, Facebook, Twitter, etc.) sont-ils réellement apatrides? Utilisent-ils des jetons ou des cookies (ou les deux)?

Si vous demandez s'ils utilisent des cookies ou des jetons pour l'authentification, la réponse est qu'ils utilisent les deux. Pour les utilisateurs, principalement des cookies pour les clients techniques, des jetons sont principalement utilisés.

5
Paul Wasilewski

Le protocole est sans état.

Mais il ne s'ensuit pas nécessairement que les applications utilisant le protocole doivent être sans état.

Voici quelques réponses StackOverflow connexes qui expliquent bien la différence:

5
sideshowbarker