web-dev-qa-db-fra.com

Concevoir / se connecter ou / enregistrer des ressources?

Je concevais une application Web, puis je me suis arrêté pour réfléchir à la manière dont mon API devrait être conçue comme un service Web RESTful. Pour l'instant, la plupart de mes URI sont génériques et peuvent s'appliquer à diverses applications Web:

GET  /logout   // destroys session and redirects to /
GET  /login    // gets the webpage that has the login form
POST /login    // authenticates credentials against database and either redirects home with a new session or redirects back to /login
GET  /register // gets the webpage that has the registration form
POST /register // records the entered information into database as a new /user/xxx
GET  /user/xxx // gets and renders current user data in a profile view
POST /user/xxx // updates new information about user

J'ai le sentiment que je me trompe beaucoup après avoir fouillé sur SO et google.

Commençant par /logout, peut-être puisque je ne fais pas vraiment GET rien - il serait peut-être plus approprié de POST une demande à /logout, détruisez la session, puis GET la redirection. Et devrait le /logout séjour temporaire?

Qu'en est-il de /login et /register. Je pourrais changer /register à /registration mais cela ne modifie pas le fonctionnement fondamental de mon service - s'il pose des problèmes plus profonds.

Je remarque maintenant que je n'expose jamais un /user Ressource. Peut-être que cela pourrait être utilisé d'une manière ou d'une autre. Par exemple, prenons l'utilisateur myUser:

foo.com/user/myUser

ou

foo.com/user

L'utilisateur final n'a pas besoin de cette verbosité supplémentaire dans l'URI. Cependant, lequel est le plus attrayant visuellement?

J'ai remarqué quelques autres questions ici sur SO à ce sujet REST entreprise, mais j'apprécierais vraiment quelques conseils sur ce que j'ai présenté ici si possible).

Merci!

PDATE:

J'aimerais aussi avoir des avis sur:

/user/1

contre

/user/myUserName
105
Qcom

Une chose ressort en particulier comme non-REST-FUL: l'utilisation d'une requête GET pour se déconnecter.

(de http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Safe_methods )

Certaines méthodes (par exemple, HEAD, GET, OPTIONS et TRACE) sont définies comme étant sûres, ce qui signifie qu'elles sont uniquement destinées à la récupération d'informations et ne doivent pas modifier l'état du serveur. En d'autres termes, ils ne devraient pas avoir d'effets secondaires, au-delà d'effets relativement inoffensifs tels que la journalisation, la mise en cache, la diffusion de bannières publicitaires ou l'incrémentation d'un compteur Web. [...]

[... H] andling [des requêtes GET] du serveur n'est techniquement d'aucune façon limitée. Par conséquent, une programmation négligente ou délibérée peut entraîner des modifications non triviales sur le serveur. Ceci est déconseillé, car cela peut poser des problèmes pour la mise en cache Web, les moteurs de recherche et autres agents automatisés [...]

En ce qui concerne la déconnexion et la redirection, vous pouvez avoir une publication dans votre URI de déconnexion, donnant une réponse 303 redirigée vers la page de post-déconnexion.

http://en.wikipedia.org/wiki/Post/Redirect/Get

http://en.wikipedia.org/wiki/HTTP_3

Modifier pour résoudre les problèmes de conception d'URL:

"Comment concevoir mes ressources?" C'est une question importante pour moi. "comment puis-je concevoir mes URL?" est une considération dans deux domaines:

Les URL que les utilisateurs verront ne doivent pas être trop laides ni significatives, si possible; Si vous souhaitez que les cookies soient envoyés à certaines ressources mais pas à d'autres, vous devrez structurer vos chemins d'accès et les chemins d'accès aux cookies.

Si JRandomUser veut consulter son propre profil et que vous souhaitez que l'URL soit plus jolie que foo.com/user/JRandomUser Ou foo.com/user/(JRandom's numeric user id here), vous pouvez créer une URL distincte, uniquement pour l'utilisateur. à leur propre information:

GET foo.com/profile /*examines cookies to figure out who 
                     * is logged in (SomeUser) and then 
                     * displays the same response as a
                     * GET to foo.com/users/SomeUser.
                     */

Je dirais que l'ignorance est beaucoup plus facile que la sagesse à ce sujet, mais voici quelques considérations sur la conception des ressources:

  1. Consommateur: quelles ressources doivent être visualisées directement dans un navigateur, chargées via XHR ou accessibles par un autre type de client?
  2. Accès/identité: la réponse dépend-elle des cookies ou des référents?
56
ellisbben

RESTful peut être utilisé comme guide pour la construction d'URL et vous pouvez créer des ressources sessions et tilisateurs:

  • GET /session/new Obtient la page Web contenant le formulaire de connexion
  • POST /session Authentifie les informations d'identification par rapport à la base de données
  • DELETE /session Détruit la session et redirige vers /
  • GET /users/new Obtient la page Web contenant le formulaire d'inscription
  • POST /users Enregistre les informations saisies dans la base de données en tant que nouveau/utilisateur/xxx
  • GET /users/xxx // récupère et restitue les données utilisateur actuelles dans une vue de profil
  • POST /users/xxx // met à jour les nouvelles informations sur l'utilisateur

Ceux-ci peuvent être au pluriel ou au singulier (je ne suis pas sûr de celui qui est correct). J'ai généralement utilisé /users Pour une page d'index utilisateur (comme prévu) et /sessions Pour voir qui est connecté (comme prévu).

Utiliser le nom dans l'URL au lieu d'un nombre (/users/43 Vs /users/joe) Est généralement motivé par le désir d'être plus convivial avec les utilisateurs ou les moteurs de recherche, sans aucune exigence technique. Soit c'est bien, mais je vous recommande d'être cohérent.

Je pense que si vous utilisez les options register/login/logout ou sign(in|up|out), cela ne fonctionnera pas aussi bien avec la terminologie reposante.

107
ndp

les sessions ne sont pas reposantes

  • Oui je sais. Cela se fait, généralement avec OAuth, mais en réalité, les sessions ne sont pas reposantes. Vous ne devriez pas avoir de ressource/login/logout principalement parce que vous ne devriez pas avoir de sessions.

  • Si vous allez le faire, rendez-le RESTful. Les ressources sont des noms et/login et/logout ne sont pas des noms. Je voudrais aller avec/session. Cela rend la création et la suppression plus naturelles.

  • POST vs GET pour les sessions est facile. Si vous envoyez utilisateur/mot de passe sous forme de variables, j'utiliserais POST car je ne souhaite pas que le mot de passe soit envoyé avec l'URI. Il apparaîtra dans les journaux et sera éventuellement exposé. Vous courez également le risque d’échec logiciel sur les limitations de GET args.

  • J'utilise généralement l'authentification de base ou aucune autorisation avec les services REST.

Création d'utilisateurs

  • C'est une ressource, vous ne devriez donc pas avoir besoin de/vous inscrire.

    • POST/utilisateur - Crée un utilisateur si le demandeur ne peut pas spécifier l'identifiant
    • PUT/user/xxx - Crée ou met à jour un utilisateur en supposant que vous connaissez déjà l'identifiant
    • GET/user - répertorie x identifiants utilisateur
    • GET/user/xxx - Récupère les détails de l'utilisateur portant l'identifiant xxx
    • DELETE/user/xxx - Supprime l'utilisateur portant l'id xxx
  • Quel type d'identifiant utiliser est une question difficile. Vous devez penser à imposer l'unicité, à la réutilisation d'anciens identifiants supprimés. Par exemple, vous ne souhaitez pas utiliser ces identifiants en tant que clés étrangères sur un backend si les identifiants vont être recyclés (dans la mesure du possible). Vous pouvez toutefois rechercher une conversion d'identifiant externe/interne afin d'atténuer les exigences du backend.

51
dietbuddha

Je vais simplement parler de mon expérience d’intégration de divers REST services Web pour mes clients, qu’ils soient utilisés pour des applications mobiles ou pour la communication entre serveurs, ainsi que de la construction REST pour les autres. Voici quelques observations que j'ai rassemblées de l'AP REST d'autres personnes) ainsi que de celles que nous avons construites nous-mêmes:

  • Lorsque nous parlons d'API, cela fait normalement référence à un ensemble d'interface de programmation et pas nécessairement à la couche de présentation. REST est également centré sur les données et non basé sur la présentation. Cela dit, la plupart REST renvoie des données sous la forme de JSON ou XML et ne renvoie que très rarement une couche de présentation spécifique. trait (de renvoyer des données et non la page Web directe) donné REST possibilité d'effectuer une livraison multi-canaux. Cela signifie que le même service Web peut être rendu en HTML, iOS, Android ou même utilisé comme combinaison de serveur à serveur.
  • Il est très rare de combiner HTML et REST sous forme d'URL. Par défaut REST sont des pensées en tant que services et ne comportant pas de couche de présentation. C'est le travail de ceux-ci. qui consomment les services Web pour restituer les données des services qu’ils appellent en fonction de ce qu’ils veulent (jusqu’à ce que votre URL ci-dessous ne soit pas conforme à la plupart des REST que j’ai rencontrée jusqu’à présent) (ni les standards tels que ceux venant de Facebook ou Twitter)
 GET/register // obtient la page Web contenant le formulaire d'inscription 
  • En continuant avec le point précédent, il est également rare (et je ne l’ai pas rencontré) pour REST de faire une redirection telle que celles suggérées ci-dessous:
 GET/logout // détruit la session et redirige vers /[.____.unsetPOST/login // authentifie les informations d'identification par rapport à la base de données et redirige la maison vers une nouvelle session ou redirige vers /login
 

En tant que REST sont conçus en tant que services, des fonctions telles que la connexion et la déconnexion renvoient normalement le résultat de réussite/échec (normalement au format de données JSON ou XML) que le consommateur interpréterait ensuite. Cette interprétation pourrait inclure redirection vers la page Web appropriée que vous avez mentionnée

  • Dans REST, l'URL indique les actions entreprises. Pour cette raison, nous devrions lever autant d'ambiguïté que possible. Bien qu'il soit légitime dans votre cas d'avoir à la fois GET et POST qui a le même chemin (tel que/register) qui effectuent des actions différentes, une telle conception introduit de l'ambiguïté dans les services fournis et peut dérouter le consommateur. Par exemple, les URL telles que celle que vous indiquez ci-dessous ne sont pas idéales pour REST
 GET/register // récupère la page Web contenant le formulaire d'inscription 
 POST/register // enregistre les informations saisies dans la base de données sous la forme d'un nouveau /user/xxx
.

Ce sont quelques points de ce que j'ai traité. J'espère que cela pourra vous aider.

En ce qui concerne l’implémentation de votre REST, voici l’implémentation typique que j’ai rencontrée:

  •  GET/logout 
    

    Exécutez la déconnexion dans le backend et renvoyez JSON pour indiquer le succès/l'échec de l'opération.

  •  POST /login
    

    Soumettez les informations d'identification au serveur. Retourner le succès/échec. En cas de succès, le jeton de session ainsi que les informations de profil sont normalement renvoyés.

  •  POST /register
    

    Soumettez votre inscription au serveur. Retourner le succès/échec. En cas de succès, le traitement est normalement identique à la connexion réussie ou vous pouvez choisir de vous enregistrer en tant que service distinct.

  •  GET /user/xxx
    

    Obtenir le profil utilisateur et renvoyer le format de données JSON pour le profil de l'utilisateur

  •  POST/user/xxx 
     // renommé en 
     POST /updateUser/xxx
    

    Publiez les informations de profil mises à jour au format JSON et mettez à jour les informations dans le backend. Renvoyer le succès/l'échec à l'appelant

20
momo

Je crois que c'est une approche RESTful à l'authentification. Pour vous connecter, utilisez HttpPut. Cette méthode HTTP peut être utilisée pour la création lorsque la clé est fournie et que les appels répétés sont idempotents. Pour LogOff, vous indiquez le même chemin sous la méthode HttpDelete. Aucun verbe utilisé. Une pluralisation correcte des collections. Les méthodes HTTP supportent l'objectif.

[HttpPut]
[Route("sessions/current")]
public IActionResult LogIn(LogInModel model) { ... }

[HttpDelete]
[Route("sessions/current")]
public IActionResult LogOff() { ... }

Si vous le souhaitez, vous pouvez remplacer le courant par le courant.

3
Chad Kuehn

Je recommanderais d'utiliser une URL de compte d'utilisateur similaire à Twitter, où l'URL du compte de l'utilisateur serait quelque chose comme foo.com/myUserName comme vous pouvez accéder à mon compte Twitter avec l’URL https://Twitter.com/joelbyler

Je ne suis pas d'accord sur la déconnexion nécessitant un POST. Dans le cadre de votre API, si vous souhaitez conserver une session, un identifiant de session sous la forme d'un UUID peut être utilisé pour suivre un utilisateur et confirmer que l'action entreprise est autorisée. Alors même un GET peut transmettre l’identifiant de session à la ressource.

En bref, je vous recommande de garder les choses simples, les URL doivent être courtes et mémorables.

2
joelbyler