Wie implementiere ich die Anmeldung in einem RESTful-Webdienst?

78

Ich erstelle eine Webanwendung mit einer Serviceschicht. Die Serviceschicht wird mit einem RESTful-Design erstellt. Es wird davon ausgegangen, dass wir in Zukunft möglicherweise andere Anwendungen (iPhone, Android usw.) erstellen, die dieselbe Serviceschicht wie die Webanwendung verwenden. Meine Frage lautet: Wie implementiere ich die Anmeldung? Ich glaube, ich habe Probleme beim Übergang von einem traditionelleren verbbasierten Design zu einem ressourcenbasierten Design. Wenn ich dies mit SOAP erstellen würde, hätte ich wahrscheinlich eine Methode namens Login. In REST sollte ich eine Ressource haben. Ich habe Schwierigkeiten zu verstehen, wie ich meine URI für eine Anmeldung erstellen soll. Sollte es so etwas sein:

http: // myservice / {Benutzername}? p = {Passwort}

BEARBEITEN: Die Front-End-Webanwendung verwendet das traditionelle ASP.NET-Framework zur Authentifizierung. Irgendwann im Authentifizierungsprozess muss ich jedoch die angegebenen Anmeldeinformationen überprüfen. In einer herkömmlichen Webanwendung würde ich eine Datenbanksuche durchführen. In diesem Szenario rufe ich jedoch einen Dienst auf, anstatt eine Datenbanksuche durchzuführen. Ich benötige also etwas im Dienst, das die angegebenen Anmeldeinformationen überprüft. Zusätzlich zur Validierung der angegebenen Anmeldeinformationen benötige ich wahrscheinlich auch Informationen über den Benutzer, nachdem er sich erfolgreich authentifiziert hat - Dinge wie sein vollständiger Name, seine ID usw. Ich hoffe, dies macht die Frage klarer.

Oder denke ich nicht richtig darüber nach? Ich habe das Gefühl, dass ich Schwierigkeiten habe, meine Frage richtig zu beschreiben.

Corey

Corey Burnett
quelle

Antworten:

62

Wie S.Lott bereits betont hat, haben wir hier zwei Dinge: Login und Authentifizierung

Die Authentifizierung ist hier nicht möglich, da dies ausführlich diskutiert wird und eine gemeinsame Übereinstimmung besteht. Was benötigen wir jedoch, damit sich ein Client erfolgreich bei einem RESTful-Webdienst authentifiziert? Richtig, eine Art Token, nennen wir es Access-Token.

Client) Also, alles was ich brauche ist ein Zugriffstoken, aber wie bekomme ich so RESTfully?
Server) Warum nicht einfach erstellen?
Kunde) Wie kommt es?
Server) Für mich ist ein Zugriffstoken nichts anderes als eine Ressource. Daher erstelle ich eine für Sie im Austausch für Ihren Benutzernamen und Ihr Passwort.

Somit könnte der Server die Ressourcen-URL "/ accesstokens" anbieten, um den Benutzernamen und das Passwort an POST zu senden und den Link zur neu erstellten Ressource "/ accesstokens / {accesstoken}" zurückzugeben. Alternativ geben Sie ein Dokument zurück, das das Zugriffstoken und eine href mit dem Link der Ressource enthält:

<Zugriffstoken
  id = "{Zugriffstoken-ID wird hier angezeigt; z. B. GUID}"
  href = "/ accesstokens / {id}"
/>

Höchstwahrscheinlich erstellen Sie das Zugriffstoken nicht als Unterressource und nehmen daher seine href nicht in die Antwort auf.
Wenn Sie dies jedoch tun, könnte der Client den Link in seinem Namen generieren oder nicht? Nein!
Denken Sie daran, dass wirklich RESTful-Webdienste Ressourcen so miteinander verknüpfen, dass der Client selbst navigieren kann, ohne Ressourcenverknüpfungen generieren zu müssen.

Die letzte Frage, die Sie wahrscheinlich haben, ist, ob Sie den Benutzernamen und das Passwort als HTML-Formular oder als Dokument, z. B. XML oder JSON, veröffentlichen sollten - es kommt darauf an ... :-)

Patrick
quelle
4
Nicht perfekt nach REST, aber einfach und messbar besser als andere. Plus mit guter Laune geteilt.
Ted Johnson
2
Patrick, schlagen Sie dasselbe vor wie diese Antwort? stackoverflow.com/a/1135995/14731
Gili
Ist 403 der richtige Statuscode, wenn Benutzername und / oder Passwort nicht übereinstimmen?
siebzehn
Was für eine Idee. Erstellen einer Zugriffsressource.
Sortierer
25

Sie "loggen" sich nicht ein. Sie "authentifizieren" sich. Welt des Unterschieds.

Sie haben viele Authentifizierungsalternativen.

HTTP Basic-, Digest-, NTLM- und AWS S3-Authentifizierung

  • HTTP Basic- und Digest-Authentifizierung. Dies verwendet den HTTP_AUTHORIZATIONHeader. Das ist sehr schön, sehr einfach. Kann aber zu viel Verkehr führen.

  • Authentifizierung mit Benutzername / Signatur. Wird manchmal als "ID and KEY" -Authentifizierung bezeichnet. Dies kann eine Abfragezeichenfolge verwenden.

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

    Dies ist, was Orte wie Amazon verwenden. Der Benutzername ist die "ID". Der "Schlüssel" ist ein Digest, ähnlich dem für die HTTP-Digest-Authentifizierung verwendeten. Beide Seiten müssen sich auf die Verdauung einigen, um fortzufahren.

  • Eine Art Cookie-basierte Authentifizierung. OpenAM kann beispielsweise als Agent konfiguriert werden, um ein Cookie zu authentifizieren und bereitzustellen, das Ihr RESTful-Webserver dann verwenden kann. Der Client würde sich zuerst authentifizieren und dann das Cookie mit jeder RESTful-Anforderung bereitstellen.

S.Lott
quelle
2
@ S.Lott @Corey Benutzer können absolut mit RESTful-Systemen interagieren. Die meisten statischen HTML-Websites sind RESTful "Dienste".
Darrel Miller
7
@Darrel Miller: "Ihre Idee ... ist fehlerhaft" bietet keinen richtigen Kontext oder irgendetwas Nützliches. Es ist irgendwie negativ und nicht zu hilfreich.
S.Lott
5
@Darrel Miller: "behaupten, REST sei beschränkt auf ... ist einfach lächerlich". Was auch immer. Könnten Sie vielleicht erklären, was richtig ist, wenn Sie wiederholen, was falsch ist? Könnten Sie eine einfache positive Aussage anstelle von negativen Aussagen machen? Können Sie erklären, was REST ist, anstatt was es nicht ist? Es gibt unendlich viele Dinge, die es nicht ist.
S.Lott
4
@Darrel Miller: 5.2.1.2 Darstellungen scheinen ziemlich klar zu sein. Ihre Kommentare sind sehr negativ. Könnten Sie positive Korrekturen oder Aktualisierungen anstelle von Negativität vornehmen? Ich kann nicht herausfinden, wie ich meine Antwort korrigieren oder ändern kann, um Sie zufrieden zu stellen, da Sie nur sagen, dass ich irgendwie "fehlerhaft" oder "falsche Informationen verbreitet" oder "lächerlich" bin. Was ist weniger fehlerhaft, weniger falsch oder weniger lächerlich?
S.Lott
5
@ S.Lott 1) ​​Benutzer interagieren ständig mit RESTful-Systemen. 2) HTML ist ein vollkommen gültiger Medientyp, den ein RESTful-System zurückgeben kann. 3) REST ist keine Teilmenge von HTTP. REST ist ein Architekturstil, HTTP ist ein Protokoll. 4) RESTful-Systeme sind nicht auf "Webdienste" beschränkt. 5) RESTful-Systeme können eine Anmeldung mithilfe eines Autorisierungstokens simulieren, ohne dass Probleme im Zusammenhang mit Sitzungen auftreten.
Darrel Miller
1

Gute Frage, gut gestellt. Ich mag Patricks Antwort wirklich. Ich benutze so etwas wie

- / users / {Benutzername} / loginsession

Mit POST und GET behandelt. Ich poste also eine neue Anmeldesitzung mit Anmeldeinformationen und kann dann die aktuelle Sitzung über das GET als Ressource anzeigen.

Die Ressource ist eine Anmeldesitzung, die möglicherweise über ein Zugriffstoken oder einen Authentifizierungscode, einen Ablauf usw. verfügt.

Seltsamerweise muss mein MVC-Aufrufer selbst ein Schlüssel- / Inhaber-Token über einen Header präsentieren, um zu beweisen, dass er das Recht hat, neue Anmeldesitzungen zu erstellen, da die MVC-Site ein Client der API ist.

Bearbeiten

Ich denke, einige andere Antworten und Kommentare hier lösen das Problem mit einem gemeinsamen Out-of-Band-Geheimnis und authentifizieren sich nur mit einem Header. Das ist in vielen Situationen oder für Service-to-Service-Anrufe in Ordnung.

Die andere Lösung besteht darin, ein Token, OAuth oder JWT oder auf andere Weise zu fließen. Dies bedeutet, dass die "Anmeldung" bereits von einem anderen Prozess durchgeführt wurde, wahrscheinlich einer normalen Anmelde-Benutzeroberfläche in einem Browser, der auf einem Formular-POST basiert.

Meine Antwort bezieht sich auf den Dienst, der sich hinter dieser Benutzeroberfläche befindet, vorausgesetzt, Sie möchten, dass Anmeldung und Authentifizierung sowie Benutzerverwaltung in einem REST-Dienst und nicht im Site-MVC-Code platziert werden. Es ist der Benutzeranmeldedienst.

Es ermöglicht auch anderen Diensten, sich anzumelden und ein ablaufendes Token zu erhalten, anstatt einen vorinstallierten Schlüssel zu verwenden, sowie Testskripte in einer CLI oder einem Postboten.

Luke Puplett
quelle
2
Übergeben Sie das Token in einem Header, ja. Übergeben Sie es als Teil der URL, nein. Die URL wird während der Übertragung verschlüsselt, wenn Sie HTTPS verwenden. Jedoch; Die URL wird auch im Browserverlauf und in Serverprotokollen gespeichert. Es gibt viele gute Gründe, die Übergabe sicherheitsrelevanter Daten in URL-Abfrageparametern zu vermeiden.
Craig
0

Da hat sich seit 2011 einiges geändert ...

Wenn Sie bereit sind, ein Tool eines Drittanbieters zu verwenden und geringfügig von REST für die Web-Benutzeroberfläche abweichen, ziehen Sie http://shiro.apache.org in Betracht .

Shiro bietet Ihnen grundsätzlich einen Servlet-Filter, der sowohl zur Authentifizierung als auch zur Autorisierung dient. Sie können alle von @ S.Lott aufgelisteten Anmeldemethoden verwenden, einschließlich einer einfachen formularbasierten Authentifizierung.

Filtern Sie die restlichen URLs, für die eine Authentifizierung erforderlich ist, und Shiro erledigt den Rest.

Ich verwende dies derzeit in meinem eigenen Projekt und es hat bisher ziemlich gut für mich funktioniert.

Hier ist noch etwas, an dem die Leute interessiert sein könnten. Https://github.com/PE-INTERNATIONAL/shiro-jersey#readme

Halbduplex
quelle
0

Das erste, was Sie über REST wissen sollten, ist, dass es sich um einen Token-basierten Ressourcenzugriff handelt. Im Gegensatz zu herkömmlichen Methoden wird der Zugriff auf der Grundlage der Token-Validierung gewährt. Mit einfachen Worten, wenn Sie das richtige Token haben, können Sie auf Ressourcen zugreifen. Jetzt gibt es viele andere Dinge für die Erstellung und Manipulation von Token.

Für Ihre erste Frage können Sie eine Restfull-API entwerfen. Anmeldeinformationen (Benutzername und Kennwort) werden an Ihre Serviceschicht übergeben. Die Serviceschicht überprüft diese Anmeldeinformationen und gewährt ein Token. Anmeldeinformationen können entweder ein einfacher Benutzername / ein einfaches Kennwort oder SSL-Zertifikate sein. SSL-Zertifikate verwenden das OAUTH-Protokoll und sind sicherer.

Sie können Ihren URI wie folgt gestalten: URI für Token-Anforderung-> http: // myservice / some-directory / token ? (Sie können Credentilals in dieser URI für Token übergeben)

Um dieses Token für den Ressourcenzugriff zu verwenden, können Sie dieses [Berechtigung: Träger (Token)] zu Ihrem http-Header hinzufügen.

Dieses Token kann vom Kunden verwendet werden, um auf verschiedene Komponenten Ihrer Serviceschicht zuzugreifen. Sie können auch die Ablaufdauer dieses Tokens ändern, um Missbrauch zu verhindern.

Bei Ihrer zweiten Frage können Sie verschiedene Token gewähren, um auf verschiedene Ressourcenkomponenten Ihrer Serviceschicht zuzugreifen. Dazu können Sie Ressourcenparameter in Ihrem Token und die Berechtigung basierend auf diesem Feld angeben.

Sie können diesen Links auch folgen, um weitere Informationen zu erhalten: 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

Rishabh Soni
quelle
-4

Ich habe das gleiche Problem schon einmal gesehen. Die Anmeldung lässt sich nicht gut auf ressourcenbasiertes Design übertragen.

Normalerweise gehe ich damit um, indem ich über eine Login-Ressource verfüge und Benutzername und Passwort an die Parameterzeichenfolge übergebe

GET on http: // myservice / login? U = {Benutzername} & p = {Passwort}

Die Antwort ist eine Art Sitzung oder Authentifizierungszeichenfolge, die dann zur Validierung an andere APIs übergeben werden kann.

Eine Alternative zu GET in der Login-Ressource ist ein POST, REST-Puristen werden mich jetzt wahrscheinlich nicht mögen :) und die Creds im Körper weitergeben. Die Antwort wäre die gleiche.

Alex
quelle
11
Passwort? Nur-Text-Passwort? Als Abfragezeichenfolge? Meinten Sie das wirklich oder meinen Sie eine Zusammenfassung des Passworts?
S.Lott
Vielen Dank. Das macht Sinn. Hier ist eine Folgefrage: Würden Sie für eine große Anwendung einen großen RESTful-Service für alles erstellen oder die Dinge in verschiedene Services aufteilen? Ich dachte daran, einen Dienst nur zur Authentifizierung und dann verschiedene Dienste für die verschiedenen Module meiner Anwendung zu haben. Gibt es Gründe, warum Sie es so oder so machen würden oder nicht?
Corey Burnett
3
S. Lott: Es hängt davon ab, was Sie versuchen zu tun. Natürlich, wenn Sie eine Verdauung machen können, dann auf jeden Fall. Manchmal ist eine Verdauung nicht möglich. Wenn die einzige Option, die Ihnen offen steht, das Senden eines Nur-Text-Passworts ist, tun Sie dies bitte über SSL. In diesem Fall ist es auch besser, einen POST zu verwenden, als GET, um zu verhindern, dass sich der Browser an das erinnert, was Sie gesendet haben.
Alex
Corey: Ich bin mir nicht sicher, ob ich den Unterschied zwischen einem großen und vielen verschiedenen Webservices verstehe. Normalerweise definieren Sie Ihren Service in Bezug auf Ressourcen und fügen nur so wenig hinzu, wie sinnvoll ist. Ich glaube, ich vermisse deinen Standpunkt.
Alex
Alex: Nehmen wir an, ich hatte 4 verschiedene Hauptabschnitte meiner Webanwendung - Berichte, Bestellungen, Downloads und Rechnungen. Wäre es sinnvoll, 4 verschiedene Service-Definitionen oder nur 1 Service-Definition zu haben? Gibt es bestimmte Gründe, warum Sie die Dinge nicht in viele verschiedene Dienste aufteilen möchten?
Corey Burnett