Si les applications REST sont censées être sans état, comment gérez-vous les sessions?

536

J'ai besoin d'éclaircissements. J'ai lu sur REST et créé des applications RESTful. Selon wikipedia, REST lui-même est défini comme étant le transfert d'état représentatif . Je ne comprends donc pas tout ce gobbledeygook apatride que tout le monde crache .

De wikipedia:

À tout moment, un client peut être en transition entre des états d'application ou "au repos". Un client en état de repos peut interagir avec son utilisateur, mais ne crée aucune charge et ne consomme aucun stockage par client sur l'ensemble des serveurs ou sur le réseau.

Est-ce qu'ils disent juste de ne pas utiliser le magasin de données de niveau session / application ???

J'obtiens que l'un des objectifs de REST est de rendre l'accès URI cohérent et disponible, par exemple, au lieu de masquer les demandes de pagination dans les publications, en faisant du numéro de page d'une demande une partie de l'URI GET. Ça a du sens pour moi. Mais il semble que cela va trop loin en disant qu'aucune donnée par client (données de session) ne doit jamais être stockée côté serveur.

Que faire si j'avais une file d'attente de messages et que mon utilisateur voulait lire les messages, mais en le lisant, il voulait bloquer certains messages d'expéditeurs pendant toute la durée de sa session? Ne serait-il pas judicieux de stocker cela dans un endroit côté serveur et de demander au serveur d'envoyer uniquement des messages (ou des ID de message) qui n'ont pas été bloqués par l'utilisateur?

Dois-je vraiment envoyer la liste complète des expéditeurs de messages à bloquer chaque fois que je demande la nouvelle liste de messages? La liste de messages qui me concerne ne serait / ne devrait même pas être une ressource accessible au public en premier lieu.

Encore une fois, j'essaie juste de comprendre cela. Quelqu'un veuillez clarifier.


Mise à jour:

J'ai trouvé une question de débordement de pile qui a une réponse qui ne me permet pas de tout faire: comment gérer l'état dans REST qui dit que l'état client qui est important devrait tous être transférés à chaque demande .... Ugg .. semble être beaucoup de frais généraux ... Est-ce vrai ??

Zak
la source
2
@ S.Lott: Je ne pense pas que ce soit intentionnellement trompeur. Je pense que c'est un malentendu à cause de la confusion de la terminologie.
JUSTE MON AVIS correct
2
@JUST MON AVIS correct: conjecture intéressante. Je ne pouvais pas croire une telle chose, moi-même, car il est évident que "sans état" signifie que le protocole REST lui-même est sans état; qui ne dit rien sur l'état de l'application sous-jacente et le met à jour avec les requêtes PUT, POST et DELETE.
S.Lott
@ S.Lott: Le protocole HTTP lui-même est sans état. D'après ce que nous avons discuté ci-dessous, REST est un point de vue sur la façon de créer votre application sans avoir l'état de session de gestion du serveur Web (par opposition à d'autres types d'état dans des choses comme la base de données). Je ne pensais même pas que REST était un protocole, mais plutôt une vue sur la façon d'utiliser le protocole HTTP. Je pensais que vous aviez clarifié qu'il s'agissait de créer votre application à l'échelle en faisant en sorte que le côté client stocke toutes les données de session spécifiques au client et en rendant les accès URI aussi idempotents que possible, sauf là où ils ne devraient pas l'être. Peut-être pas ... :(
Zak
1
"Peut-être pas .." Qu'est-ce que cela signifie? Vous avez une nouvelle question? N'hésitez pas à rechercher SO pour cela. S'il n'existe pas ici, demandez-le.
S.Lott
Quelqu'un a-t-il lu Webber, Parastatidis et Robinson's ReST dans la pratique (ou autrement vu leur exemple de restbucks)? Les réponses ci-dessous ont du sens, mais les commandes de café dans l'exemple restbucks sont sûrement des informations sur un client? Le nombre de commandes évolue avec le nombre de clients. Où est la frontière entre l'état du client et une ressource?
Rikki

Réponses:

340

L'apatridie signifie que chaque requête HTTP se produit dans un isolement complet. Lorsque le client fait une demande HTTP, il inclut toutes les informations nécessaires au serveur pour répondre à cette demande. Le serveur ne s'appuie jamais sur les informations des requêtes précédentes. Si ces informations sont importantes, le client devra les renvoyer lors d'une demande ultérieure. L'apatridie apporte également de nouvelles fonctionnalités. Il est plus facile de distribuer une application sans état sur des serveurs à charge équilibrée. Une application sans état est également facile à mettre en cache.

Il existe en fait deux types d'État. État d'application résidant sur le client et État de ressource résidant sur le serveur.

Un service Web n'a besoin de prendre en compte l'état de votre application que lorsque vous effectuez une demande. Le reste du temps, il ne sait même pas que vous existez. Cela signifie que chaque fois qu'un client fait une demande, il doit inclure tous les états d'application dont le serveur aura besoin pour la traiter.

L'état des ressources est le même pour chaque client et sa place appropriée se trouve sur le serveur. Lorsque vous téléchargez une image sur un serveur, vous créez une nouvelle ressource: la nouvelle image a son propre URI et peut être la cible de futures requêtes. Vous pouvez récupérer, modifier et supprimer cette ressource via HTTP.

J'espère que cela aide à différencier ce que l'apatridie et divers états signifient.

Srikar Doddi
la source
4
Cela signifie-t-il que chaque fois qu'une demande est envoyée, le client doit envoyer son utilisateur / mot de passe pour s'authentifier? Parce que je suppose que stocker une session, même si elle se trouve sur une base de données no-sql partagée entre tous les serveurs, n'est pas sans état, ou l'est-ce?
Carlos Navarro Astiasarán
1
@ CarlosNavarroAstiasarán il existe différentes techniques pour gérer l'authentification sans état. Google JWT par exemple.
géoidesic
1
@geoidesic: "Parce que les jetons Web JSON sont sans état, il n'y a aucun moyen de les invalider sans stocker l'état du serveur, annulant ainsi l'avantage des jetons sans état." WIkipedia
ulatekh
@ulatekh C'est une déformation grossière de ce que vous pouvez faire avec les jetons. Il est assez simple de stocker un ID approuvé avec le jeton et d'accepter uniquement les jetons qui ont un ID approuvé en tant que revendication. Sans état ne signifie pas que vous ne pouvez rien dans une base de données. Essentiellement, vous stockez un ID dans la base de données qui doit correspondre au même ID dans le jeton. Pour révoquer le jeton, vous supprimez l'ID de la base de données. Aucun état n'est mémorisé dans le service lui-même. Ou encore mieux, vous stockez la clé de signe avec l'utilisateur dans la base de données et révoquez la clé.
Andrew T Finnell
@AndrewTFinnell: Si vous devez stocker l'ID approuvé sur le serveur, il doit être stocké sur tous les serveurs potentiels qui pourraient traiter la connexion REST, ce qui pourrait impliquer beaucoup d'état de serveur sur une architecture de serveur Web massivement parallèle.
ulatekh
491

L'explication fondamentale est:

Aucun état de session client sur le serveur.

Par sans état, cela signifie que le serveur ne stocke aucun état concernant la session client côté serveur.

La session client est stockée sur le client. Le serveur est sans état signifie que chaque serveur peut desservir n'importe quel client à tout moment, il n'y a pas d' affinité de session ou de sessions persistantes . Les informations de session pertinentes sont stockées sur le client et transmises au serveur selon les besoins.

Cela n'empêche pas les autres services auxquels le serveur Web parle de maintenir l'état des objets métier tels que les paniers d'achat, mais pas de l'état actuel de l'application / session du client.

L' état d'application du client ne doit jamais être stocké sur le serveur, mais transmis du client à chaque endroit qui en a besoin.

C'est de là que vient la ST dans REST , State Transfer . Vous transférez l'état autour au lieu d'avoir le serveur le stocker. C'est le seul moyen d'évoluer vers des millions d'utilisateurs simultanés. Si pour aucune autre raison que parce que des millions de sessions sont des millions de sessions.

La charge de gestion de session est amortie sur tous les clients, les clients stockent leur état de session et les serveurs peuvent desservir de nombreux ordres de grandeur ou plusieurs clients de manière apatride.

Même pour un service dont vous pensez qu'il n'aura besoin que dans les dizaines de milliers d'utilisateurs simultanés, vous devez toujours rendre votre service apatride. Des dizaines de milliers, c'est encore des dizaines de milliers et il y aura du temps et de l'espace associés.

Sans état est la façon dont le protocole HTTP et le Web en général ont été conçus pour fonctionner.

Il existe des principes de mise en œuvre très basiques:

Ce sont des principes et non des implémentations, la façon dont vous respectez ces principes peut varier.

En résumé, les cinq principes clés sont les suivants:

  1. Donnez à chaque «chose» un identifiant
  2. Reliez les choses ensemble
  3. Utiliser des méthodes standard
  4. Des ressources aux représentations multiples
  5. Communiquer apatride

Il n'y a rien sur l'authentification ou l'autorisation dans la thèse REST .

Parce qu'il n'y a rien de différent que d'authentifier une requête qui est RESTful de celle qui ne l'est pas. L'authentification n'est pas pertinente pour la discussion RESTful.

Expliquer comment créer une application sans état pour vos besoins particuliers est trop large pour StackOverflow.

L'implémentation de l'authentification et de l'autorisation en ce qui concerne REST est encore plus large et diverses approches d'implémentation sont expliquées en détail sur Internet en général.

Les commentaires demandant de l'aide / des informations à ce sujet seront / devraient simplement être signalés comme n'étant plus nécessaires .


la source
22
Cela semble être une déclaration assez audacieuse selon laquelle c'est le seul moyen de s'adapter à des millions d'utilisateurs. Pourquoi les sessions côté serveur ne peuvent-elles pas être simplement un autre service?
Zak
27
@Zak: Parce que des millions de sessions c'est des millions de sessions. Le but est d'éviter la surcharge de toute cette gestion de session.
S.Lott
91
ce n'est pas de l'audace c'est de l'expérience
21
Rien dans ma réponse n'implique une solution basée sur l'accès à la base de données à chaque demande, si vous le pensez, c'est un échec de votre part à comprendre l'authentification et l'autorisation à cette échelle. L'authentification peut être implicite dans l'état, pensez-vous que facebook effectue un "accès à la base de données" à chaque demande de son API REST? Ou Google d'ailleurs? indice: non
6
Donc, si je stocke l'état utilisateur dans un cache distribué, par exemple memcache, et que tout mon serveur Web n'a plus besoin de stocker aucun état mais d'aller chercher l'état à partir de memcache, puis-je considérer cette application sans état?
Jaskey
76

Est-ce qu'ils disent juste de ne pas utiliser le magasin de données de niveau session / application ???

Non, ils ne disent pas cela d'une manière triviale.

Ils disent de ne pas définir de "session". Ne vous connectez pas. Ne vous déconnectez pas. Fournissez les informations d'identification avec la demande. Chaque demande est indépendante.

Vous avez toujours des magasins de données. Vous avez toujours l'authentification et l'autorisation. Vous ne perdez pas de temps à établir des sessions et à maintenir l'état de session.

Le fait est que chaque demande (a) est complètement isolée et (b) peut être trivialement transformée en une batterie de serveurs parallèle géante sans aucun travail réel. Apache ou Squid peuvent transmettre des requêtes RESTful à l'aveugle et avec succès.

Que faire si j'avais une file d'attente de messages et que mon utilisateur voulait lire les messages, mais en le lisant, il voulait bloquer certains messages d'expéditeurs pendant toute la durée de sa session?

Si l'utilisateur veut un filtre, fournissez simplement le filtre à chaque demande.

Ne serait-il pas logique que le serveur envoie uniquement des messages (ou des ID de message) qui n'ont pas été bloqués par l'utilisateur?

Oui. Fournissez le filtre dans la demande d'URI RESTful.

Dois-je vraiment envoyer la liste complète des expéditeurs de messages à bloquer chaque fois que je demande la nouvelle liste de messages?

Oui. Quelle est la taille de cette "liste des expéditeurs de messages à bloquer"? Une courte liste de PK?

Une demande GET peut être très importante. Si nécessaire, vous pouvez essayer une requête POST même si cela ressemble à une sorte de requête.

S.Lott
la source
28
"Ne vous connectez pas. Ne vous déconnectez pas. Fournissez les informations d'identification avec la demande." Je vois toujours des réponses comme celle-ci dans les questions sur la façon de rester apatride dans une API REST sans aucun détail sur où / comment on doit stocker ces informations d'identification sur le client. Certes, nous ne devrions pas stocker le nom d'utilisateur et le mot de passe dans le stockage local!
BeniRose
2
@BeniRose ne pouvons-nous pas stocker un jeton dans le stockage local et utiliser ce jeton dans des demandes qui identifieront uniquement l'utilisateur?
Nikhil Sahu
1
Localstorage a beaucoup de problèmes de sécurité d'après ce que je comprends. Mais il y a aussi un tas d'autres problèmes avec les sessions côté client, comme invalider les jetons, déconnecter un utilisateur, etc.
BeniRose
3
vous utilisez JWT qui a une signature, la vérification de la signature est rapide afin que vous puissiez vérifier la validité de cet état.
Archimedes Trajano
36

Vous avez absolument raison, la prise en charge d'interactions complètement sans état avec le serveur impose une charge supplémentaire au client. Cependant, si vous envisagez de faire évoluer une application, la puissance de calcul des clients est directement proportionnelle au nombre de clients. Par conséquent, l'adaptation à un nombre élevé de clients est beaucoup plus réalisable.

Dès que vous mettez un tout petit peu de responsabilité sur le serveur pour gérer certaines informations liées aux interactions d'un client spécifique, cette charge peut rapidement augmenter pour consommer le serveur.

C'est un compromis.

Darrel Miller
la source
32

Vue historique de la gestion de l'état des applications utilisateur

Les sessions au sens traditionnel conservent l'état de l'utilisateur dans l'application à l'intérieur du serveur. Il peut s'agir de la page en cours dans un flux ou de ce qui a été précédemment entré mais qui n'a pas encore été conservé dans la base de données principale.

La raison de ce besoin était le manque de normes côté client pour maintenir efficacement l'état sans créer d'applications ou de plug-ins spécifiques au client (c'est-à-dire spécifiques au navigateur).

Au fil du temps, HTML5 et XML Header Request ont normalisé la notion de stockage de données complexes, y compris l' état de l'application, de manière standard côté client (c'est-à-dire navigateur) sans recourir à des allers-retours entre les serveurs.

Utilisation générale des services REST

Les services REST sont généralement appelés lorsqu'une transaction doit être effectuée ou si elle doit récupérer des données.

Les services REST sont censés être appelés par l'application côté client et non directement par l'utilisateur final.

Authentification

Pour toute demande adressée au serveur, une partie de la demande doit contenir le jeton d'autorisation. La façon dont il est implémenté est spécifique à l'application, mais en général, c'est une forme BASICou une CERTIFICATEforme d'authentification.

L'authentification basée sur le formulaire n'est pas utilisée par les services REST. Cependant, comme indiqué ci-dessus, les services REST ne sont pas destinés à être appelés par l'utilisateur, mais par l'application. L'application doit gérer l'obtention du jeton d'authentification. Dans mon cas, j'ai utilisé des cookies avec JASPIC avec OAuth 2.0 pour me connecter à Google pour l'authentification et l' authentification HTTP simple pour les tests automatisés. J'ai également utilisé l' authentification HTTP Header via JASPIC pour les tests locaux (bien que la même approche puisse être effectuée dans SiteMinder)

Selon ces exemples, l'authentification est gérée côté client (bien que SiteMinder ou Google stockent la session d'authentification de leur côté), il n'y a rien qui puisse être fait à propos de cet état, mais cela ne fait pas partie de l'application de service REST.

Demandes de récupération

Les demandes de récupération dans REST sont des GETopérations dans lesquelles une ressource spécifique est demandée et peut être mise en cache. Il n'y a pas besoin de sessions serveur car la requête a tout ce dont elle aurait besoin pour récupérer les données: l'authentification et l'URI.

Scripts de transaction

Comme indiqué ci-dessus, l'application côté client appelle elle-même les services REST ainsi que l'authentification qu'elle gère également côté client.

Ce que cela signifie pour les services REST [si cela est fait correctement], c'est de soumettre une seule demande au serveur REST qui contiendra tout ce qui est nécessaire pour une opération utilisateur unique qui fait tout ce qui est nécessaire dans une seule transaction, un script de transaction est ce que le modèle est appelé.

Cela se fait généralement par le biais d'une POSTdemande, mais d'autres tels que PUTpeuvent également être utilisés.

Beaucoup d'exemples artificiels de REST (j'ai moi-même fait cela) ont essayé de suivre autant de ce qui a été défini dans le protocole HTTP, après avoir traversé cela, j'ai décidé d'être plus pragmatique et de le laisser à GET et POST uniquement . La POSTméthode n'a même pas à implémenter le modèle POST-REDIRECT-GET.

Quoi qu'il en soit, comme je l'avais noté ci-dessus, l'application côté client sera celle qui appelle le service et elle n'appellera la POSTdemande avec toutes les données que quand elle en aura besoin (pas à chaque fois). Cela empêche des demandes constantes au serveur.

Vote

Bien que REST puisse également être utilisé pour l'interrogation, je ne le recommanderai pas sauf si vous devez l'utiliser en raison de la compatibilité du navigateur. Pour cela, j'utiliserais WebSockets pour lequel j'avais également conçu un contrat d'API . Une autre alternative pour les navigateurs plus anciens est CometD.

Archimedes Trajano
la source
27

REST est très abstrait. Il est utile d'avoir de bons exemples simples et concrets.

Prenez par exemple toutes les principales applications de médias sociaux - Tumblr, Instagram, Facebook et Twitter. Ils ont tous une vue à défilement permanent où plus vous faites défiler vers le bas, plus vous voyez de contenu, de plus en plus loin dans le temps. Cependant, nous avons tous connu ce moment où vous perdez à l'endroit où vous avez été fait défiler et l'application vous réinitialise en haut. Comme si vous quittez l'application, puis lorsque vous la rouvrez, vous êtes de nouveau au sommet.

La raison en est que le serveur n'a pas enregistré votre état de session. Malheureusement, votre position de défilement vient d'être stockée dans la mémoire RAM du client.

Heureusement, vous n'avez pas à vous reconnecter lorsque vous vous reconnectez, mais c'est uniquement parce que votre certificat de connexion stocké côté client n'a pas expiré. Supprimez et réinstallez l'application et vous devrez vous reconnecter, car le serveur n'a pas associé votre adresse IP à votre session.

Vous n'avez pas de session de connexion sur le serveur, car ils respectent REST.


Maintenant, les exemples ci-dessus n'impliquent pas du tout un navigateur Web, mais à l'arrière, les applications communiquent via HTTPS avec leurs serveurs hôtes. Mon point est que REST n'a pas à impliquer les cookies et les navigateurs, etc. Il existe différents moyens de stocker l'état de la session côté client.

Mais parlons des navigateurs Web pendant une seconde, car cela apporte un autre avantage majeur de REST dont personne ne parle ici.

Si le serveur a tenté de stocker l'état de la session, comment est-il censé identifier chaque client individuel?

Il ne pouvait pas utiliser leur adresse IP, car de nombreuses personnes pouvaient utiliser cette même adresse sur un routeur partagé. Alors comment?

Il ne peut pas utiliser l'adresse MAC pour de nombreuses raisons, notamment parce que vous pouvez être connecté à plusieurs comptes Facebook différents simultanément sur différents navigateurs et l'application. Un navigateur peut facilement prétendre en être un autre, et les adresses MAC sont tout aussi faciles à usurper.

Si le serveur doit stocker un état côté client pour vous identifier, il doit le stocker dans la RAM plus longtemps que le temps nécessaire pour traiter vos demandes, ou bien il doit mettre en cache ces données. Les serveurs ont des quantités limitées de RAM et de cache, sans parler de la vitesse du processeur. L'état côté serveur s'ajoute aux trois, de façon exponentielle. De plus, si le serveur doit stocker un état de vos sessions, il doit le stocker séparément pour chaque navigateur et application avec lesquels vous êtes actuellement connecté, ainsi que pour chaque appareil différent que vous utilisez.


Alors ... j'espère que vous voyez maintenant pourquoi REST est si important pour l'évolutivité. J'espère que vous pourrez commencer à voir pourquoi l'état de la session côté serveur est à l'évolutivité du serveur ce que les enclumes soudées sont à l'accélération de la voiture.


Là où les gens sont confus, c'est en pensant que «état» fait référence, comme, aux informations stockées dans une base de données. Non, cela fait référence à toute information qui doit se trouver dans la mémoire RAM du serveur lorsque vous l'utilisez.

CommaToast
la source
13

Je vois que la question fondamentale ici est de mélanger Session avec État . Et bien que REST spécifie que vous ne devez PAS stocker l' état sur le serveur, rien ne vous empêche de stocker une session utilisateur .

La gestion de l' état sur le serveur signifie que votre serveur sait exactement ce que fait le client (quelle page il affiche dans quelle section de l'application). Et c'est ce que vous ne devriez pas faire.

Je suis d'accord avec les autres personnes disant que vous devez garder le stockage de session à une taille minimale; et bien que ce soit du bon sens, cela dépend aussi de l'application. Donc, en bref, vous pouvez toujours conserver une session avec des données mises en cache pour gérer les demandes avec moins de charge sur le serveur et gérer l'authentification en fournissant un jeton d'authentification / d'accès temporaire que le client peut utiliser. Chaque fois que la session / le jeton est expiré, générez-en un nouveau et demandez au client de l'utiliser.

Quelqu'un pourrait faire valoir que le client devrait mieux générer le jeton. Je dis que cela fonctionne dans les deux sens, et cela dépend de l'application et de qui va travailler avec l'API.

La conservation de certaines données de session sensibles sur le serveur devrait également être la bonne façon de procéder. Vous ne pouvez pas faire confiance au client pour conserver son panier qui (par exemple) contient un champ nommé "isFreeGift". Ces informations doivent être conservées sur le serveur.

Le lien vidéo fourni par Santanu Dey dans sa réponse est utile. Regardez-le si vous ne l'avez pas fait.

Juste une remarque: il semble que toutes les réponses déjà données semblent ignorer le fait que certaines opérations pourraient entraîner une lourde charge sur le serveur. C'est pertinent en termes de consommation d'énergie, de matériel et de coût (pour les serveurs loués par cycle CPU). Un bon développeur ne devrait pas être paresseux dans l'optimisation de son application, même si l'opération peut se faire très rapidement sur un CPU moderne sur un serveur loué pour lequel il ne paie pas sa facture d'électricité et de maintenance.

Bien que la question date de quelques années, j'espère que ma réponse sera toujours utile.

Sam Sirry
la source
4
Je suis généralement d'accord avec ce sentiment, mais il y a eu une tendance récente à prétendre que même un identifiant de session ne devrait pas être stocké sur le serveur. Je n'ai pas encore découvert quelle est la solution alternative, JWT est bien présenté, mais est livré avec une poignée de pièges
BeniRose
11

Sans état signifie que l'état du service ne persiste pas entre les demandes et les réponses ultérieures. Chaque demande porte ses propres informations d'identification d'utilisateur et est authentifiée individuellement. Mais en état, chaque demande est connue de toute demande antérieure. Toutes les demandes avec état sont orientées session, c'est-à-dire que chaque demande doit connaître et conserver les modifications apportées dans les demandes précédentes.

L'application bancaire est un exemple d'application avec état. Où l'utilisateur se connecte d'abord, puis effectue la transaction et se déconnecte. Si après la déconnexion, l'utilisateur tentera d'effectuer la transaction, il ne pourra pas le faire.

Oui, le protocole http est essentiellement un protocole sans état mais pour le rendre dynamique, nous nous faisons de cookies HTTP. Donc, SOAP est par défaut. Mais il peut également être rendu avec état, cela dépend du framework que vous utilisez.

HTTP est sans état mais nous pouvons toujours maintenir la session dans notre application java en utilisant un mécanisme de suivi de session différent.

Oui, nous pouvons également maintenir la session dans le service Web, que ce soit REST ou SOAP. Il peut être implémenté en utilisant n'importe quelle bibliothèque tierce ou vous pouvez l'implémenter par nos propres moyens.

Tiré de http://gopaldas.org/webservices/soap/webservice-is-stateful-or-stateless-rest-soap

Ata ul Mustafa
la source
11

Il n'y a pas de cuillère.

Ne pensez pas à l'apatridie comme "envoyer encore et encore toutes vos affaires au serveur". En aucune façon. Il y aura toujours un état - la base de données elle - même est une sorte d'état après tout, vous êtes un utilisateur enregistré, donc tout ensemble d'informations côté client ne sera pas valide sans le côté serveur. Techniquement, vous n'êtes jamais vraiment apatride.

Un mot sur le débat sur la connexion à chaque fois

Qu'est-ce que cela signifie même de ne pas garder une session et de se connecter à chaque fois? Certains signifient «envoyer le mot de passe à chaque fois», c'est tout simplement stupide. Certains disent "non, bien sûr que non, envoyez un jeton à la place" - et voilà, la session PHP fait presque exactement cela. Il envoie un identifiant de session qui est une sorte de jeton et il vous aide à accéder à vos données personnelles sans renvoyer u / pw à chaque fois. Il est également assez fiable et bien testé. Et oui, pratique, ce qui peut se transformer en inconvénient, voir paragraphe suivant.

Réduisez l'empreinte

Ce que vous devez faire à la place et ce qui est vraiment logique, c'est réduire au minimum votre empreinte de serveur Web. Des langages comme PHP facilitent le remplissage de tout dans le stockage de session, mais les sessions ont un prix. Si vous avez plusieurs serveurs Web, ils doivent partager les informations de session, car ils partagent également la charge - chacun d'entre eux devra peut-être répondre à la prochaine demande.

Un stockage partagé est indispensable. Le serveur doit savoir au moins si quelqu'un est connecté ou non. (Et si vous dérangez la base de données chaque fois que vous devez en décider, vous êtes pratiquement condamné.) Les stockages partagés doivent être beaucoup plus rapides que la base de données. Cela amène la tentation: d' accord, j'ai un stockage très rapide, pourquoi ne pas tout faire là-bas? - et c'est là que les choses vont mal dans l'autre sens.

Vous dites donc, garder le stockage de session au minimum?

Encore une fois, c'est votre décision. Vous pouvez y stocker des éléments pour des raisons de performances (la base de données est presque toujours plus lente que Redis), vous pouvez stocker des informations de manière redondante, implémenter votre propre mise en cache, peu importe - gardez à l'esprit que les serveurs Web auront une charge plus importante si vous stockez beaucoup de déchets sur eux. De plus, s'ils se brisent sous de lourdes charges (et ils le feront), vous perdez des informations précieuses; avec la façon de penser REST, tout ce qui se passe dans ce cas est que le client envoie à nouveau la même (!) demande et qu'elle est servie cette fois.

Comment le faire alors?

Pas de solution universelle ici. Je dirais que je choisis un niveau d'apatridie et j'y vais. Les sessions peuvent être aimées par certains et détestées par d'autres, mais elles ne vont nulle part. À chaque demande, envoyez autant d'informations que possible, un peu plus peut-être; mais n'interprétez pas l'apatridie comme n'ayant pas de session, ni comme se connectant à chaque fois. D'une manière ou d'une autre, le serveur doit savoir que c'est vous ; Les identifiants de session PHP sont un bon moyen, les jetons générés manuellement en sont un autre.

Pensez et décidez, ne laissez pas les tendances du design penser à votre place.

dkellner
la source
1
"Réfléchissez et décidez, ne laissez pas les tendances du design penser à votre place." malheureusement, il devient très courant de nos jours de suivre bêtement les tendances. Parfois, en lisant SO, vous obtiendrez toutes les mêmes réponses juste à cause de la tendance.
l00k
Oui, j'ai vu cela autour de nombreux sujets et quand je me rends compte de ce qui se passe, parfois j'arrête de me disputer. À l'époque, tout le monde était fou de la façon dont content-box est meilleur que border-box; c'était une façon de montrer la haine contre IE. Puis vint le bootstrap et tout à coup tout le monde était un croyant aux frontières. Les tendances viennent mais elles disparaissent. Utilisez goto, utilisez des tableaux, utilisez des iframes, sachez simplement ce que vous faites et pourquoi. Les Trendists essaieront de vous abattre, puis ils s'inscrivent et paient sur votre site. Le monde a de nouveau sauvé.
dkellner
@dkellner Je n'ai pas compris cette partie: "Le serveur doit savoir au moins si quelqu'un est connecté ou non. (Et si vous dérangez la base de données à chaque fois que vous devez en décider, vous êtes pratiquement condamné.)". Supposons que vous stockiez les données de session dans la base de données avec PHP. Pourquoi l'interrogation de la base de données pour la connexion est-elle mauvaise (condamné est un mot fort) car de toute façon il y aura de nombreuses demandes de base de données ultérieures pour obtenir les données utilisateur complètes et d'autres choses, basées sur l'ID de session PHP? En d'autres termes, les requêtes DB sont inévitables dans tous les cas. De plus, si vous ne recevez pas d'ID de session PHP, vous savez que l'utilisateur n'est pas authentifié, pas besoin d'interroger.
user2923322
Lorsque vous avez des milliers, voire des millions d'utilisateurs, vous ne pouvez pas vous permettre le luxe de vous connecter à db chaque fois que vous souhaitez effectuer une persistance, une mise à jour de l'emplacement, un sondage de message ou tout ce qui nécessite un bref enregistrement. Vous devez implémenter ces appels sans (ou avec un accès minimal) à la base de données, c'est pourquoi je dis que cela peut être mortel si vous construisez tout votre concept autour de db. Encore une fois, il peut y avoir des cas où une solution de base de données bien conçue fonctionnera, mais le programmeur typique résoudra tout en disant "d'accord, d'abord nous nous connectons et récupérons des informations utilisateur". Pratique Baaaad.
dkellner
5

Jetez un œil à cette présentation.

http://youtu.be/MRxTP-rQ-S8

Selon ce modèle - créez des ressources transitoires reposantes pour gérer l'état si et quand vous en avez vraiment besoin. Évitez les sessions explicites.

Santanu Dey
la source
1
Veuillez lire Comment écrire une bonne réponse? avant d'essayer de répondre à plus de questions.
3

La principale différence entre stateless et Stateful réside dans le fait que les données sont à chaque fois renvoyées au serveur. En cas d'apatridie, le client doit fournir toutes les informations, de sorte que de nombreux paramètres peuvent devoir être transmis à chaque demande. Dans Stateful, la cliet passe ces paramètres une fois et ils sont maintenus par le serveur jusqu'à ce qu'ils soient à nouveau modifiés par le client.

IMO, l'API devrait être sans état, ce qui permet une mise à l'échelle très rapide.

psuhas
la source
2

Vous devez gérer la session client côté client. Cela signifie que vous devez envoyer des données d'authentification à chaque demande, et vous avez probablement, mais pas nécessairement, un cache en mémoire sur le serveur, qui associe les données d'authentification aux informations utilisateur telles que l'identité, les autorisations, etc.

Cette contrainte d'apatridie REST est très importante. Sans l' application de cette contrainte, votre application côté serveur ne sera pas l' échelle , parce que maintenant chaque session client unique sera son talon d'Achille .

inf3rno
la source
Si vous envoyez des données d'authentification à chaque demande, où / comment stockez-vous les informations d'identification sur le client afin que l'utilisateur n'ait pas à les ressaisir à chaque demande?
Amber
1

Lorsque vous développez un service RESTful, pour être connecté, vous aurez besoin que votre utilisateur soit authentifié. Une option possible serait d'envoyer le nom d'utilisateur et le mot de passe chaque fois que vous avez l'intention d'effectuer une action utilisateur. Dans ce cas, le serveur ne stockera pas du tout les données de session.

Une autre option consiste à générer un identifiant de session sur le serveur et à l'envoyer au client, afin que le client puisse envoyer l'identifiant de session au serveur et s'authentifier avec cela. C'est beaucoup plus sûr que d'envoyer le nom d'utilisateur et le mot de passe à chaque fois, car si quelqu'un met la main sur ces données, il peut alors se faire passer pour l'utilisateur jusqu'à ce que le nom d'utilisateur et le mot de passe soient modifiés. Vous pouvez dire que même l'ID de session peut être volé et que l'utilisateur sera usurpé dans ce cas et vous avez raison. Cependant, dans ce cas, l'emprunt d'identité de l'utilisateur ne sera possible que si l'ID de session est valide.

Si l'API RESTful attend le nom d'utilisateur et le mot de passe pour changer le nom d'utilisateur et le mot de passe, même si quelqu'un a usurpé l'identité de l'utilisateur à l'aide de l'ID de session, le pirate ne pourra pas verrouiller le véritable utilisateur.

Un identifiant de session pourrait être généré par le verrouillage unidirectionnel (chiffrement) de quelque chose qui identifie l'utilisateur et en ajoutant l'heure à l'identifiant de session, de cette façon le temps d'expiration de la session pourrait être défini.

Le serveur peut ou non stocker les identifiants de session. Bien sûr, si le serveur stocke l'ID de session, cela violerait les critères définis dans la question. Cependant, il est seulement important de s'assurer que l'ID de session peut être validé pour l'utilisateur donné, ce qui ne nécessite pas de stocker l'ID de session. Imaginez un moyen de cryptage unidirectionnel des e-mails, de l'ID utilisateur et de certaines données privées spécifiques à l'utilisateur, comme la couleur préférée, ce serait le premier niveau et en quelque sorte l'ajout de la date du nom d'utilisateur à la chaîne cryptée et appliquer une double - cryptage de manière. Par conséquent, lorsqu'un identifiant de session est reçu, le deuxième niveau pourrait être déchiffré pour pouvoir déterminer le nom d'utilisateur que l'utilisateur prétend être et si l'heure de la session est correcte. Si cela est valide, le premier niveau de cryptage pourrait alors être validé en effectuant à nouveau ce cryptage et en vérifiant s'il correspond à la chaîne. Vous n'avez pas besoin de stocker les données de session pour y parvenir.

Lajos Arpad
la source
cela a du sens
mestarted
0

Le concept est différent ... Vous n'avez pas besoin de gérer les sessions si vous essayez d'implémenter le protocole RESTFul. Dans ce cas, il est préférable de faire une procédure d'authentification à chaque demande (alors qu'il y a un coût supplémentaire en termes de performances - le hachage du mot de passe serait un bon exemple. Pas un gros problème ...). Si vous utilisez des sessions - comment répartir la charge sur plusieurs serveurs? Je parie que le protocole RESTFul est destiné à éliminer les sessions - vous n'en avez pas vraiment besoin ... C'est pourquoi il est appelé "sans état". Les sessions ne sont nécessaires que lorsque vous ne pouvez pas stocker autre chose que des cookies côté client après qu'une demande a été effectuée (prenez l'exemple d'un ancien navigateur prenant en charge Javascript / HTML5). En cas de client RESTFul "complet", il est généralement sûr de stockerbase64(login:password) côté client (en mémoire) jusqu'à ce que l'appliction soit toujours chargée - l'application est utilisée pour accéder au seul hôte et le cookie ne peut pas être compromis par les scripts tiers ...

Je recommande vivement de désactiver l'authentification par cookie pour les services RESTFul ... consultez Basic / Digest Auth - cela devrait être suffisant pour les services basés sur RESTFul.

user3857922
la source
3
Qu'est-ce que a client side (in memory) et comment est-il sûr d'enregistrer base64(login:password)côté client?
RN Kushwaha
1
Rien n'est défini comme «totalement sûr». Cependant, vous pouvez envisager d'utiliser OAuth2 pour une meilleure sécurité que l'enregistrement de la chaîne base64 pour la demande d'API (Basic Auth), si vous vous en tenez à Basic auth, vous pouvez utiliser HTTPS pour une meilleure sécurité.
felixwcf
3
RN Kushwaha, c'est la question à laquelle personne ne semble vouloir répondre quand ils vous disent d'arrêter de stocker la session sur le serveur et de la stocker dans le client.
BeniRose
0

REST est sans état et ne conserve aucun état entre les demandes. Les cookies / en-têtes client sont définis pour maintenir l'état de l'utilisateur comme l'authentification. Supposons que le nom d'utilisateur / mot de passe du client est validé par un mécanisme d'authentification tiers - gernation OTP de deuxième niveau, etc. . Maintenant, certaines informations sur l'utilisateur comme IP sont conservées dans le cache et après cela, si la demande provient du même IP (adresse mac) pour les ressources répertoriées, l'utilisateur est autorisé. Et le cache est maintenu pendant un certain temps qui est invalidé une fois le temps écoulé. Donc, soit le cache peut être utilisé, soit les entrées de base de données peuvent être utilisées pour conserver les informations n / b sur les demandes.

Amit
la source
0

Sans état signifie ici que l'état ou les métadonnées de la demande ne sont pas conservés côté serveur. En maintenant l'état de chaque requête ou utilisateur sur le serveur, cela entraînerait des goulots d'étranglement des performances. Le serveur est simplement demandé avec les attributs requis pour effectuer des opérations spécifiques.

En ce qui concerne la gestion des sessions ou la personnalisation de l'expérience des utilisateurs, il nécessite de conserver certaines métadonnées ou l'état des préférences de l'utilisateur probable, l'historique des demandes passées. Cela peut être fait en conservant les cookies, les attributs cachés ou dans l'objet de session.

Cela peut maintenir ou suivre l'état de l'utilisateur dans l'application.

J'espère que cela t'aides!

Sourabh Bhavsar
la source