73

Je construis une application web avec une couche de services. La couche de services va être construite en utilisant un design RESTful. Nous pensons que dans le futur nous pourrons construire d'autres applications (iPhone, Android, etc.) qui utilisent la même couche de services que l'application web. Ma question est la suivante: comment implémenter la connexion? Je pense que j'ai du mal à passer d'une conception verbale plus traditionnelle à une conception basée sur les ressources. Si je construisais cela avec SOAP, j'aurais probablement une méthode appelée Login. Dans REST, je devrais avoir une ressource. J'ai de la difficulté à comprendre comment je devrais construire mon URI pour un login. Devrait-il être quelque chose comme ceci:Comment implémenter la connexion dans un service Web RESTful?

http://myservice/ {nom d'utilisateur} p = {} mot de passe

EDIT: L'application Web frontal utilise le cadre de ASP.NET traditionnel pour l'authentification. Cependant, à un certain moment dans le processus d'authentification, j'ai besoin de valider les informations d'identification fournies. Dans une application web traditionnelle, je ferais une recherche dans la base de données. Mais dans ce scénario, j'appelle un service au lieu de faire une recherche dans la base de données. J'ai donc besoin de quelque chose dans le service qui permettra de valider les informations d'identification fournies. Et en plus de valider les informations d'identification fournies, j'ai probablement besoin d'informations sur l'utilisateur une fois qu'elles ont été authentifiées avec succès - des choses comme leur nom complet, leur identifiant, etc. J'espère que cela clarifiera la question. Ou est-ce que je ne pense pas à ça de la bonne manière? J'ai l'impression d'avoir de la difficulté à décrire correctement ma question.

Corey

Répondre

55

Comme S. Lott ont déjà signalé, nous avons deux choses pliées: Connectez-vous et l'authentification

L'authentification est hors du champ d'ici, car cela est largement discuté et il est d'un commun accord. Cependant, de quoi avons-nous réellement besoin pour qu'un client s'authentifie avec succès contre un service Web RESTful? À droite, une sorte de jeton, appelons-le access-token. Client) Donc, tout ce dont j'ai besoin est un jeton d'accès, mais comment obtenir RESTfully?
Serveur) Pourquoi ne pas simplement le créer?
Client) Comment ça se passe?
Server) Pour moi, un access-token n'est rien d'autre qu'une ressource. Ainsi, je vais en créer un pour vous en échange de votre nom d'utilisateur et mot de passe.

Ainsi, le serveur pourrait offrir l'URL de ressource "/ accesstokens", pour POSTER le nom d'utilisateur et le mot de passe, renvoyant le lien à la ressource nouvellement créée "/ accesstokens/{accesstoken}". Sinon, vous retournez un document contenant l'accès jeton et a href avec le lien de la ressource:

 
<access-token 
    id="{access token id goes here; e.g. GUID}" 
    href="/accesstokens/{id}" 
/> 

Très probablement, vous ne créez pas réellement l'accès symbolique en tant que sous-ressource et donc, ne comprendra pas son href dans la réponse.
Cependant, si vous le faites, le client pourrait générer le lien en son nom ou non? Non! Rappelez-vous que les services Web véritablement RESTful lient les ressources de manière à ce que le client puisse naviguer lui-même sans avoir besoin de générer des liens de ressources.

La dernière question que vous avez probablement est de savoir si vous devez POSTER le nom d'utilisateur et mot de passe comme un formulaire HTML ou comme un document, par exemple. XML ou JSON - ça dépend ... :-)

+3

Ne suit pas parfaitement REST, mais un simple et mesurable mieux que d'autres. Plus partagé avec bonne humeur. –

+1

Patrick, proposez-vous la même chose que cette réponse? http://stackoverflow.com/a/1135995/14731 – Gili

+0

Le code d'état correct est-il 403 lorsque le nom d'utilisateur et/ou le mot de passe ne correspondent pas? – sevteen

-4

J'ai déjà fait face au même problème. Connexion ne se traduit pas bien à la conception basée sur les ressources.

La façon dont je gère habituellement il est en ayant des ressources de connexion et le nom d'utilisateur qui passe et mot de passe sur la chaîne de paramètres, font essentiellement

GET sur http://myservice/login?u= {nom d'utilisateur} & p = {password}

La réponse est une sorte de chaîne de session ou d'authentification qui peut ensuite être transmise à d'autres API pour validation.

Une alternative à faire GET sur la ressource de connexion est de faire un POST, les puristes REST ne m'apprécieront probablement pas maintenant :), et en passant les creds dans le corps. La réponse serait la même.

+11

mot de passe? Mot de passe en texte brut?En tant que chaîne de requête? Vouliez-vous vraiment dire cela, ou voulez-vous dire un condensé du mot de passe? –

+0

Merci. Ça a du sens. Voici une question complémentaire: pour une grande application, créez-vous un grand service RESTful pour tout ou divisez les choses en différents services? Je pensais avoir un service juste pour l'authentification et ensuite différents services pour les différents modules de mon application. Y a-t-il des raisons pour lesquelles vous le feriez ou non d'une façon ou d'une autre? –

+2

S. Lott: Cela dépend de ce que vous essayez de faire. Bien sûr, si vous pouvez faire un résumé, alors par tous les moyens. Parfois, un résumé n'est pas possible. Si la seule option qui vous est offerte est l'envoi d'un mot de passe en texte clair, faites-le sur SSL, dans ce cas, il vaut mieux utiliser un POST plutôt que GET pour empêcher le navigateur de se souvenir de ce que vous avez envoyé. – Alex

22

Vous ne vous reconnectez pas. Vous "authentifiez". Monde de la différence.

Vous avez beaucoup d'alternatives d'authentification.

HTTP Basic, Digest, NTLM and AWS S3 Authentication

  • HTTP de base et l'authentification Digest. Cela utilise l'en-tête HTTP_AUTHORIZATION. C'est très gentil, très simple. Mais peut conduire à beaucoup de trafic.

  • Authentification nom d'utilisateur/signature. Parfois appelée authentification "ID et KEY". Cela peut utiliser une chaîne de requête.

    ?username=this&signature=some-big-hex-digest

    C'est ce que des endroits comme l'utilisation Amazon. Le nom d'utilisateur est le "id". La "clé" est un résumé, similaire à celui utilisé pour l'authentification HTTP Digest. Les deux parties doivent s'entendre sur le résumé pour continuer.

  • Une sorte d'authentification basée sur les cookies. Par exemple, OpenAM peut être configuré en tant qu'agent pour s'authentifier et fournir un cookie que votre serveur Web RESTful peut ensuite utiliser. Le client s'authentifierait d'abord, puis fournirait le cookie avec chaque requête RESTful.

+0

Peut-être que je dois clarifier ma question. Les utilisateurs qui visitent le site Web n'interagiront pas directement avec le service RESTful. Ils interagiront avec l'application Web. Ainsi, lorsqu'un utilisateur tente de se connecter à l'application Web, l'application Web appelle le service Web (en utilisant le code C#). Ensuite, en fonction de la réponse du service Web, le code les connecte ou non à l'application Web. Cela a-t-il du sens? Je ne suis pas sûr que les méthodes d'authentification que vous avez suggérées fonctionneront puisque le navigateur de l'utilisateur n'interagit pas directement avec le service. –

+0

@Corey Burnett: Correct. Les utilisateurs ne peuvent pas interagir avec un service Web RESTful. Correct. Les applications Web appellent les services Web. Toutes ces méthodes sont spécifiquement conçues pour qu'une application C# fasse une requête RESTful avec les informations d'identification appropriées et reçoive une réponse. Un service Web RESTful ne gère jamais "login" car il n'a pas de sessions. Il peut gérer l'authentification en acceptant que la demande est valide. Nous avons une demande "factice" qui répond simplement avec un "200 OK" si les informations d'identification sont bonnes. –

+2

@ S.Lott @Corey Les utilisateurs peuvent absolument interagir avec les systèmes RESTful. La plupart des sites Web HTML statiques sont des «services» RESTful. –

0

Depuis un peu a changé depuis 2011 ...

Si vous êtes ouvert à l'aide d'un outil 3ème partie, et déviant légèrement un peu du repos pour l'interface Web, considérez http://shiro.apache.org. Shiro vous donne fondamentalement un filtre de servlet destiné à l'authentification et à l'autorisation. Vous pouvez utiliser toutes les méthodes de connexion répertoriées par @ S.Lott, y compris une authentification basée sur un formulaire simple.

Filtrez les autres URL nécessitant une authentification, et Shiro s'occupera du reste. J'utilise actuellement ceci dans mon propre projet et cela a fonctionné assez bien pour moi jusqu'à présent.

est ici quelque chose d'autre gens peuvent être intéressés. https://github.com/PE-INTERNATIONAL/shiro-jersey#readme

1

Grande question, bien posé. J'aime vraiment la réponse de Patrick.J'utilise quelque chose comme

-/users/{nom d'utilisateur}/loginsession

Avec POST et GET manipulé. Donc, je poste une nouvelle session de connexion avec les informations d'identification et je peux ensuite voir la session en cours comme une ressource via le GET.

La ressource est une session de connexion, et qui peut avoir un code de jeton ou auth accès, expiration, etc.

Étrangement, mon appelant MVC doit se présenter un jeton de clé/porteur via un en-tête pour prouver que il a le droit d'essayer et de créer de nouvelles sessions de connexion puisque le site MVC est un client de l'API.

Modifier

Je pense que d'autres réponses et commentaires ici résolvent le problème avec un secret hors bande partagée et juste l'authentification avec un en-tête. C'est bien dans de nombreuses situations ou pour les appels de service à service. L'autre solution consiste à lancer un jeton, OAuth ou JWT ou autre, ce qui signifie que la "connexion" a déjà eu lieu par un autre processus, probablement une interface de connexion normale dans un navigateur basé sur un formulaire POST. Ma réponse est pour le service qui se trouve derrière cette interface utilisateur, en supposant que vous voulez la connexion et la gestion auth et utilisateur placé dans un service REST et non dans le code MVC du site. C'est le service de connexion d'utilisateur.

Elle permet également à d'autres services de se «connecter» et d'obtenir un jeton expirant, au lieu d'utiliser une clé prépartagée, ainsi que de tester des scripts dans un CLI ou un Postman.

+2

Passez le jeton dans un en-tête, oui. Passez-le dans le cadre de l'URL, non. L'URL est cryptée en transit lorsque vous utilisez HTTPS. Toutefois; l'URL est également stockée dans l'historique du navigateur et dans les journaux du serveur. Il y a beaucoup de bonnes raisons pour éviter de transmettre des données sensibles à la sécurité dans les paramètres de requête d'URL. – Craig

0

La première chose à comprendre à propos de REST est qu'il s'agit d'un accès aux ressources basé sur Token. À la différence des méthodes traditionnelles, l'accès est accordé sur la base de la validation de jeton. En termes simples, si vous avez le bon jeton, vous pouvez accéder aux ressources. Maintenant, il y a beaucoup d'autres choses pour la création et la manipulation de jetons.

Pour votre première question, vous pouvez concevoir une API Restfull. Les informations d'identification (nom d'utilisateur et mot de passe) seront transmises à votre couche de service. La couche de service valide alors ces informations d'identification et octroie un jeton. Les références peuvent être un simple nom d'utilisateur/mot de passe ou peuvent être des certificats SSL. Les certificats SSL utilisent le protocole OAUTH et sont plus sécurisés.

Vous pouvez concevoir votre URI comme ceci- URI pour la demande de jetons->http://myservice/some-directory/token? (Vous pouvez transmettre des identifiants dans cet URI pour Token)

Pour utiliser ce jeton pour l'accès aux ressources, vous pouvez ajouter ceci [Authorization: Bearer (token)] à votre en-tête http.

Ce jeton peut être utilisé par le client pour accéder à différents composants de votre couche de service. Vous pouvez également modifier la période d'expiration de ce jeton pour éviter toute utilisation abusive. Pour votre deuxième question, une chose que vous pouvez faire est d'accorder un jeton différent pour accéder à différents composants de ressources de votre couche de service. Pour cela, vous pouvez spécifier un paramètre de ressource dans votre jeton, et une grande autorisation basée sur ce champ.

Vous pouvez également suivre ces liens pour plus d'infos http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST

http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

Questions connexes