Pouvez-vous m'aider à comprendre cela? "Erreurs REST courantes: les sessions ne sont pas pertinentes"

159

Avis de non-responsabilité: je suis nouveau dans l'école de pensée REST et j'essaie de comprendre.

Donc, je lis cette page, Erreurs courantes de REST , et j'ai trouvé que je suis complètement déconcerté par la section sur les sessions qui n'est pas pertinente. Voici ce que dit la page:

Il ne devrait pas être nécessaire pour un client de «se connecter» ou de «démarrer une connexion». L'authentification HTTP est effectuée automatiquement sur chaque message. Les applications clientes consomment des ressources et non des services. Il n'y a donc rien à quoi se connecter! Disons que vous réservez un vol sur un service Web REST. Vous ne créez pas de nouvelle connexion «session» avec le service. Vous demandez plutôt à "l'objet créateur d'itinéraire" de vous créer un nouvel itinéraire. Vous pouvez commencer à remplir les vides, mais ensuite obtenir un composant totalement différent ailleurs sur le Web pour remplir d'autres vides. Il n'y a pas de session donc il n'y a pas de problème de migration de l'état de session entre les clients. Il n'y a pas non plus de problème d '"affinité de session"

D'accord, j'obtiens que l'authentification HTTP se fait automatiquement sur chaque message - mais comment? Le nom d'utilisateur / mot de passe est-il envoyé avec chaque demande? Cela n'augmente-t-il pas simplement la surface d'attaque? J'ai l'impression de manquer une partie du puzzle.

Serait-il mauvais d'avoir un service REST, par exemple, /sessionqui accepte une demande GET, où vous passeriez un nom d'utilisateur / mot de passe dans le cadre de la demande, et renvoie un jeton de session si l'authentification a réussi, cela pourrait être alors transmis avec les demandes ultérieures? Est-ce que cela a du sens du point de vue REST, ou est-ce que cela manque le point?

Rob
la source
chaque demande est toujours authentifiée, le détournement de session est une chose. reposant rend cela plus évident mais pas plus exposé.
Jasen

Réponses:

79

Pour être RESTful, chaque requête HTTP doit transporter suffisamment d'informations par elle-même pour que son destinataire puisse la traiter pour être en parfaite harmonie avec la nature sans état de HTTP.

D'accord, j'obtiens que l'authentification HTTP se fait automatiquement sur chaque message - mais comment?

Oui, le nom d'utilisateur et le mot de passe sont envoyés à chaque demande. Les méthodes courantes pour ce faire sont l'authentification d'accès de base et l' authentification d'accès Digest . Et oui, un espion peut capturer les informations d'identification de l'utilisateur. On crypterait ainsi toutes les données envoyées et reçues en utilisant Transport Layer Security (TLS) .

Serait-il mauvais d'avoir un service REST, disons, / session, qui accepte une demande GET, où vous passeriez un nom d'utilisateur / mot de passe dans le cadre de la demande, et renvoie un jeton de session si l'authentification a réussi, cela pourrait être ensuite transmis avec les demandes ultérieures? Cela a-t-il un sens du point de vue REST ou est-ce que cela manque le point?

Ce ne serait pas RESTful car il porte un état, mais c'est cependant assez courant car c'est pratique pour les utilisateurs; un utilisateur n'a pas à se connecter à chaque fois.

Ce que vous décrivez dans un "jeton de session" est généralement appelé cookie de connexion . Par exemple, si vous essayez de vous connecter à votre compte Yahoo! compte il y a une case à cocher qui dit "me garder connecté pendant 2 semaines". C'est essentiellement dire (dans vos mots) "garder mon jeton de session en vie pendant 2 semaines si je me connecte avec succès." Les navigateurs Web enverront de tels cookies de connexion (et éventuellement d'autres) à chaque requête HTTP que vous leur demandez de faire pour vous.

z8000
la source
5
Cette réponse n'a aucun sens pour moi. Tout d'abord, il dit que vous pouvez transmettre le login et le mot de passe à chaque fois et donc aussi une fois, ce qui est logique. Ensuite, l'idée de renvoyer au client l'état de connexion réussi sous la forme d'un jeton est suggérée. Si nécessaire, le jeton peut encoder l'heure de création. Nous sommes certainement autorisés à renvoyer des informations au client. Donc, cette suggestion me semble bien. La réponse dit que ce n'est pas bien parce que "il porte un état", mais l'idée de "ST" dans "REST" n'est-elle pas que cet état peut être transféré entre le client et le serveur?
33

Il n'est pas rare qu'un service REST exige une authentification pour chaque requête HTTP. Par exemple, Amazon S3 exige que chaque demande ait une signature dérivée des informations d'identification de l'utilisateur, de la demande exacte à effectuer et de l'heure actuelle. Cette signature est facile à calculer côté client, peut être rapidement vérifiée par le serveur, et est d'une utilité limitée pour un attaquant qui l'intercepte (puisqu'elle est basée sur l'heure actuelle).

Greg Hewgill
la source
3
+1 pouvez-vous préciser: est-il d'une utilité limitée pour un attaquant qui l'intercepte (car il est basé sur l'heure actuelle) ? Ne parlez-vous pas d'un cookie contenant un nom d'utilisateur et un mot de passe cryptés? comme SO fait? (IMHO)
Royi Namir
2
@RoyiNamir: Je ne parle pas d'un cookie. La signature utilisée par S3 est un paramètre de la requête HTTP, mais n'est pas un cookie, elle est recalculée pour chaque requête.
Greg Hewgill
Donc, si j'ai besoin de sauvegarder des informations sur un utilisateur, où les enregistrer? en db? Je ne veux pas aller chaque demande à db .... et je veux toujours utiliser le repos .... pouvez-vous s'il vous plaît aider?
Royi Namir
@RoyiNamir: Si vous avez des questions spécifiques sur la façon d'atteindre un objectif, posez une nouvelle question . Je ne peux pas répondre à des questions supplémentaires ici dans les commentaires.
Greg Hewgill
10

Beaucoup de gens ne comprennent pas très clairement les principes de REST, utiliser un jeton de session ne signifie pas toujours que vous êtes avec état, la raison d'envoyer un nom d'utilisateur / mot de passe à chaque demande est uniquement pour l'authentification et la même chose pour l'envoi d'un jeton (généré par connexion process) juste pour décider si le client a l'autorisation de demander des données ou non, vous ne violez les convétions REST que lorsque vous utilisez soit un nom d'utilisateur / mot de passe ou des jetons de session pour décider quelles données afficher! au lieu de cela, vous devez les utiliser uniquement pour une authentification (pour afficher ou ne pas afficher les données)

dans votre cas, je dis OUI, c'est RESTy, mais essayez d'éviter d'utiliser des sessions PHP natives dans votre API REST et commencez à générer vos propres jetons hachés qui expirent dans un laps de temps déterminé!

Mal Penseur
la source
1
Merci. pourquoi devrait-on éviter la session PHP native et utiliser ses propres jetons de hachage à la place?
Matthew du
pas une raison brillante que je dis, juste pour plus de sécurité et plus de contrôle.
EvilThinker
C'est mieux que la réponse acceptée. Au moins, il accepte la suggestion comme RESTy, ce qui a du sens. Cependant, je ne vois pas pourquoi les informations transmises ne peuvent pas être utilisées pour faire une autorisation dépendante de l'utilisateur. Certains utilisateurs peuvent avoir accès à certaines données et d'autres non. Cela ne rend pas le protocole non RESTful.
8

Non, ça ne manque pas le point. ClientLogin de Google fonctionne exactement de cette manière, à l'exception notable du fait que le client est invité à accéder à la "/ session" en utilisant une réponse HTTP 401. Mais cela ne crée pas de session, cela crée uniquement un moyen pour les clients de s'authentifier (temporairement) sans passer les informations d'identification en clair, et pour le serveur de contrôler la validité de ces informations d'identification temporaires comme il l'entend.

mogsie
la source
11
@ impardonnable3 Tant que le jeton retourné est uniquement utilisé pour authentifier l'utilisateur et non utilisé par le serveur pour associer l'utilisateur à un autre état stocké sur le serveur, alors je ne vois aucune contrainte REST violée.
Darrel Miller
4
@ impardonnable3 Le jeton retourné par le serveur est, en effet, la preuve que l'utilisateur est bien qui il prétend être. Ainsi, au lieu de chaque demande comprenant le nom d'utilisateur et le mot de passe, chaque demande inclut le jeton qui est construit de telle manière que le serveur puisse être sûr de sa véracité.
Darrel Miller
1
@ impardonnable3, Darrel a raison. Le jeton renvoyé en écho devrait être envoyé par le client à chaque requête HTTP, tout comme dans l'authentification Digest de base, jusqu'à ce que le jeton expire. Lorsque cela se produit, le client peut répéter la connexion, demandant éventuellement à l'utilisateur des informations d'identification, ou autre. Je pourrais élaborer la réponse, si vous le souhaitez. edit: (Et merci de suivre les réponses aux anciennes questions!)
mogsie
1
Pas de problème, mogsie, toujours intéressant de discuter de ce genre de choses :-) Je pense que je vois où vous allez avec ça, malheureusement je ne comprends tout simplement pas assez sur l'authentification Digest pour vraiment comprendre cela (surtout je ne comprendre comment le jeton est renvoyé à chaque requête HTTP, mais cela semble être un détail d'implémentation). Cependant, je vois maintenant pourquoi cette méthode ne viole pas les principes REST. Merci pour les réponses!
Rob
6
@ impardonnable3, cela peut aider: le jeton est une information signée. Il est donc autonome. Le serveur peut valider le jeton sans vérifier un état précédemment stocké. Il s'agit donc simplement d'un état stocké sur le client et transféré dans les deux sens.
Iravanchi
5

D'accord, j'obtiens que l'authentification HTTP se fait automatiquement sur chaque message - mais comment?

"Autorisation:" En-tête HTTP envoyé par le client. Soit de base (texte brut) ou de résumé.

Serait-il mauvais d'avoir un service REST, disons, / session, qui accepte une demande GET, où vous passeriez un nom d'utilisateur / mot de passe dans le cadre de la demande, et renvoie un jeton de session si l'authentification a réussi, cela pourrait être ensuite transmis avec les demandes ultérieures? Cela a-t-il un sens du point de vue REST ou est-ce que cela manque le point?

L'idée de la session est de faire stateful applications utilisant le protocole sans état (HTTP) et le client muet (navigateur Web), en maintenant l'état du côté du serveur. L'un des principes REST est "Chaque ressource est adressable de manière unique à l'aide d'une syntaxe universelle à utiliser dans les liens hypermédia" . Les variables de session ne sont pas accessibles via l'URI. Une application vraiment RESTful maintiendrait l'état du côté du client, en envoyant toutes les variables nécessaires via HTTP, de préférence dans l'URI.

Exemple: recherche avec pagination. Vous auriez une URL sous forme

http://server/search/urlencoded-search-terms/page_num

Cela a beaucoup en commun avec les URL pouvant être ajoutées aux favoris

vartec
la source
4
Les informations d'authentification ne sont pas non plus accessibles via URI, cependant - tout le monde parle d'envoyer des informations d'authentification dans le cadre de l'en-tête de la demande. En quoi est-ce différent d'inclure un jeton de session avec la demande? Je ne dis pas utiliser le jeton de session dans l'URI, mais dans les données transmises dans la demande.
Rob
L'authentification établit si vous êtes autorisé à exécuter cette action et, dans l'application RESTful, n'affecterait pas son résultat.
vartec
4
Un jeton de session établit également si vous êtes autorisé à exécuter cette action. Que voulez-vous dire que cela n'affecterait pas son résultat? Si l'appelant n'est pas autorisé, il obtient une erreur Non autorisé. Même chose avec un jeton de session. Je ne vois vraiment pas la différence?
Rob
3
Non, le jeton de session est un descripteur d' état enregistré sur le serveur. Ce n'est tout simplement pas RESTful. Quant aux Non Autorisés, je ne vois pas cela comme un résultat. Je préfère considérer cela comme une exception (comme dans try / catch).
vartec
Assez juste, vartec - cela a du sens. Merci pour le suivi!
Rob
3

Je pense que votre suggestion est correcte, si vous souhaitez contrôler la durée de vie de la session client. Je pense que l'architecture RESTful vous encourage à développer des applications sans état. Comme @ 2pence l'a écrit "chaque requête HTTP doit transporter suffisamment d'informations par elle-même pour que son destinataire puisse la traiter pour être en parfaite harmonie avec la nature sans état de HTTP" .

Cependant, ce n'est pas toujours le cas, parfois l'application a besoin de dire quand le client se connecte ou se déconnecte et de maintenir des ressources telles que des verrous ou des licences en fonction de ces informations. Voir ma question de suivi pour un exemple d'un tel cas.

LiorH
la source