Was bedeutet RESTful Authentication und wie funktioniert es? Ich kann bei Google keinen guten Überblick finden. Ich verstehe nur, dass man den Sitzungsschlüssel (remeberal) in der URL übergibt, aber das könnte schrecklich falsch sein.
Antworten
Zu viele Anzeigen?Wie die Authentifizierung in einer RESTful Client-Server-Architektur zu handhaben ist, ist umstritten.
In der Regel kann dies in der SOA over HTTP-Welt über erreicht werden:
- HTTP-Basisauthentifizierung über HTTPS;
- Cookies und Sitzungsmanagement;
- Token in HTTP-Headern (z. B. OAuth 2.0 + JWT);
- Abfrage der Authentifizierung mit zusätzlichen Signaturparametern.
Sie müssen diese Techniken anpassen oder besser noch mischen, damit sie bestenfalls zu Ihrer Softwarearchitektur passen.
Jedes Authentifizierungsschema hat seine eigenen Vor- und Nachteile, je nach Zweck Ihrer Sicherheitsrichtlinie und Softwarearchitektur.
HTTP-Basisauthentifizierung über HTTPS
Diese erste Lösung, die auf dem Standard-HTTPS-Protokoll basiert, wird von den meisten Webdiensten verwendet.
GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Es ist einfach zu implementieren, standardmäßig in allen Browsern verfügbar, hat aber einige bekannte Nachteile, wie das schreckliche Authentifizierungsfenster, das auf dem Browser angezeigt wird und bestehen bleibt (es gibt hier keine LogOut-ähnliche Funktion), einen gewissen serverseitigen zusätzlichen CPU-Verbrauch und die Tatsache, dass der Benutzername und das Passwort (über HTTPS) an den Server übertragen werden (es sollte sicherer sein, das Passwort nur auf der Client-Seite zu belassen, während der Tastatureingabe, und es als sicheren Hash auf dem Server zu speichern).
Wir können verwenden Digest-Authentifizierung aber es erfordert auch HTTPS, da es anfällig ist für MiM o Wiederholen Sie Angriffe und ist spezifisch für HTTP.
Sitzung über Cookies
Um ehrlich zu sein, ist eine auf dem Server verwaltete Sitzung nicht wirklich zustandslos.
Eine Möglichkeit wäre, alle Daten innerhalb des Cookie-Inhalts zu speichern. Das Cookie wird von vornherein auf der Serverseite verwaltet (der Client versucht nicht einmal, diese Cookie-Daten zu interpretieren: er übergibt sie einfach bei jeder nachfolgenden Anfrage an den Server zurück). Bei diesen Cookie-Daten handelt es sich jedoch um Anwendungsstatusdaten, die in einer rein zustandslosen Welt vom Client und nicht vom Server verwaltet werden sollten.
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
Die Cookie-Technik selbst ist HTTP-verknüpft, also nicht wirklich RESTful, was IMHO protokollunabhängig sein sollte. Sie ist anfällig für MiM o Wiederholen Sie Angriffe.
Erteilt über Token (OAuth2)
Eine Alternative besteht darin, ein Token in die HTTP-Header aufzunehmen, damit die Anfrage authentifiziert wird. Das ist es, was OAuth 2.0, zum Beispiel. Siehe den RFC 6749 :
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer mF_9.B5f-4.1JqM
Kurz gesagt, dies ist einem Cookie sehr ähnlich und leidet unter den gleichen Problemen: nicht zustandslos, abhängig von HTTP-Übertragungsdetails und abhängig von eine Vielzahl von Sicherheitslücken - einschließlich MiM und Replay - und ist daher nur über HTTPS zu verwenden. Typischerweise wird eine JWT wird als Token verwendet.
Abfrage der Authentifizierung
Die Abfrageauthentifizierung besteht darin, dass jede RESTful-Anfrage über einige zusätzliche Parameter im URI signiert wird. Siehe dieser Referenzartikel .
Sie wurde in diesem Artikel als solche definiert:
Alle REST-Abfragen müssen durch Signierung der Abfrageparameter authentifiziert werden sortiert in Kleinbuchstaben und in alphabetischer Reihenfolge unter Verwendung der privaten Zugangsdaten als Signier-Token. Das Signieren sollte vor der URL-Kodierung des Abfragezeichenkette erfolgen.
Diese Technik ist vielleicht am ehesten mit einer zustandslosen Architektur vereinbar und kann auch mit einer leichten Sitzungsverwaltung (unter Verwendung von In-Memory-Sitzungen anstelle von DB-Persistenz) implementiert werden.
Hier ist zum Beispiel ein allgemeines URI-Beispiel aus dem obigen Link:
GET /object?apiKey=Qwerty2010
sollten als solche übermittelt werden:
GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789
Die zu signierende Zeichenfolge lautet /object?apikey=Qwerty2010×tamp=1261496500
und die Signatur ist der SHA256-Hash dieser Zeichenfolge unter Verwendung der privaten Komponente des API-Schlüssels.
Die serverseitige Zwischenspeicherung von Daten kann immer verfügbar sein. In unserem Framework werden die Antworten beispielsweise auf SQL-Ebene und nicht auf URI-Ebene zwischengespeichert. Durch Hinzufügen dieses zusätzlichen Parameters wird der Cache-Mechanismus also nicht unterbrochen.
Ver dieser Artikel für einige Details zur RESTful-Authentifizierung in unserem Client-Server-ORM/SOA/MVC-Framework, basierend auf JSON und REST. Da wir die Kommunikation nicht nur über HTTP/1.1, sondern auch über Named Pipes oder GDI-Nachrichten (lokal) ermöglichen, haben wir versucht, ein echtes RESTful-Authentifizierungsmuster zu implementieren und uns nicht auf HTTP-Spezifika (wie Header oder Cookies) zu verlassen.
Spätere Anmerkung Das Hinzufügen einer Signatur in den URI kann als schlechte Praxis angesehen werden (da sie z. B. in den Protokollen des HTTP-Servers erscheint) und muss daher abgeschwächt werden, z. B. durch eine angemessene TTL, um Wiederholungen zu vermeiden. Aber wenn Ihre http-Protokolle kompromittiert sind, werden Sie sicherlich größere Sicherheitsprobleme haben.
In der Praxis wird die kommende MAC-Token-Authentifizierung für OAuth 2.0 kann eine enorme Verbesserung gegenüber dem derzeitigen "Granted by Token"-System darstellen. Dies ist jedoch noch in der Entwicklung und an die HTTP-Übertragung gebunden.
Schlussfolgerung
Es lohnt sich, die Schlussfolgerung zu ziehen, dass REST nicht nur HTTP-basiert ist, auch wenn es in der Praxis meist ebenfalls über HTTP implementiert wird. REST kann auch andere Kommunikationsschichten verwenden. Eine RESTful-Authentifizierung ist also nicht einfach ein Synonym für eine HTTP-Authentifizierung, egal was Google antwortet. Sie sollte sogar den HTTP-Mechanismus überhaupt nicht verwenden, sondern von der Kommunikationsschicht abstrahiert werden. Und wenn Sie HTTP-Kommunikation verwenden, können Sie dank der Let's Encrypt-Initiative Es gibt keinen Grund, kein ordnungsgemäßes HTTPS zu verwenden, das zusätzlich zu jedem Authentifizierungsverfahren erforderlich ist.
Ich bezweifle, dass die Leute, die enthusiastisch "HTTP-Authentifizierung" schreien, jemals versucht haben, eine browserbasierte Anwendung (anstelle eines Maschine-zu-Maschine-Webdienstes) mit REST zu erstellen (nichts für ungut - ich glaube nur nicht, dass sie jemals mit den Komplikationen konfrontiert wurden).
Bei der Verwendung der HTTP-Authentifizierung für RESTful-Dienste, die HTML-Seiten zur Anzeige in einem Browser erzeugen, habe ich folgende Probleme festgestellt:
- Der Benutzer erhält in der Regel ein hässliches, vom Browser erstelltes Anmeldefeld, das sehr benutzerunfreundlich ist. Sie können keine Kennwortabfrage, Hilfefelder usw. hinzufügen.
- Abmelden oder Anmelden unter einem anderen Namen ist ein Problem - die Browser senden so lange Authentifizierungsinformationen an die Website, bis Sie das Fenster schließen.
- Zeitüberschreitungen sind schwierig
Ein sehr aufschlussreicher Artikel, der diese Fragen Punkt für Punkt aufgreift, ist aquí aber dies führt zu einer Los von browserspezifischem Javascript-Hacking, Workarounds für Workarounds und so weiter. Als solches ist es auch nicht vorwärtskompatibel, so dass es ständig gewartet werden muss, wenn neue Browser veröffentlicht werden. Ich halte das nicht für ein sauberes und klares Design, und ich empfinde es als eine Menge zusätzlicher Arbeit und Kopfschmerzen, nur damit ich meinen Freunden mit Begeisterung mein REST-Abzeichen zeigen kann.
Ich glaube, dass Cookies die Lösung sind. Aber Moment, Kekse sind doch böse, oder? Nein, sie sind nicht böse, aber die Art und Weise, wie Cookies oft verwendet werden, ist böse. Ein Cookie selbst ist nur eine Information auf der Client-Seite, genau wie die HTTP-Authentifizierungsdaten, die der Browser beim Surfen speichert. Diese client-seitigen Informationen werden bei jeder Anfrage an den Server gesendet, genau wie die HTTP-Authentifizierungsdaten. Der einzige konzeptionelle Unterschied besteht darin, dass die Inhalt dieses Teils des clientseitigen Zustands kann durch den Server als Teil seiner Antwort.
Indem man Sitzungen zu einer RESTful-Ressource macht, die nur die folgenden Regeln beachtet:
- A Sitzung ordnet einen Schlüssel einer Benutzerkennung zu (und möglicherweise einem Zeitstempel der letzten Aktion für Zeitüberschreitungen)
- Wenn ein Sitzung existiert, bedeutet dies, dass der Schlüssel gültig ist.
- Login bedeutet POSTing an /sessions, ein neuer Schlüssel wird als Cookie gesetzt
- Abmelden bedeutet DELETE von /sessions/{key} (mit dem überladenen POST, bedenken Sie, dass wir ein Browser sind und HTML 5 noch lange nicht ausgereift ist)
- Die Authentifizierung erfolgt durch Senden des Schlüssels als Cookie bei jeder Anfrage und Überprüfung, ob die Sitzung existiert und gültig ist.
Der einzige Unterschied zur HTTP-Authentifizierung besteht nun darin, dass der Authentifizierungsschlüssel vom Server generiert und an den Client gesendet wird, der ihn zurücksendet, anstatt dass der Client ihn aus den eingegebenen Anmeldedaten berechnet.
converter42 fügt hinzu, dass es bei der Verwendung von https (was wir tun sollten) wichtig ist, dass das Flag für Sicherheit im Cookie gesetzt ist, damit die Authentifizierungsdaten niemals über eine unsichere Verbindung gesendet werden. Ein guter Punkt, den ich selbst noch nicht gesehen hatte.
Ich glaube, dass dies eine ausreichende Lösung ist, die gut funktioniert, aber ich muss zugeben, dass ich nicht genug Sicherheitsexperte bin, um potenzielle Lücken in diesem Schema zu erkennen - ich weiß nur, dass Hunderte von nicht-RESTful-Webanwendungen im Wesentlichen das gleiche Anmeldeprotokoll verwenden ($_SESSION in PHP, HttpSession in Java EE usw.). Der Inhalt des Cookie-Headers wird einfach verwendet, um eine serverseitige Ressource zu adressieren, so wie eine accept-language verwendet werden kann, um auf Übersetzungsressourcen zuzugreifen, und so weiter. Ich bin der Meinung, dass es dasselbe ist, aber vielleicht sehen andere das anders? Was denken Sie?
Zu diesem Thema wurde von den guten Leuten hier schon genug gesagt. Aber hier sind meine 2 Cents.
Es gibt 2 Arten der Interaktion:
- Mensch-zu-Maschine (HTM)
- Maschine-zu-Maschine (MTM)
Die Maschine ist der gemeinsame Nenner, ausgedrückt durch die REST-APIs, und die Akteure/Clients sind entweder Menschen oder Maschinen.
In einer echten RESTful-Architektur impliziert das Konzept der Zustandslosigkeit, dass alle relevanten Anwendungszustände (d. h. die Zustände auf der Client-Seite) mit jeder einzelnen Anfrage übermittelt werden müssen. Mit "relevant" ist gemeint, dass alles, was die REST-API benötigt, um die Anfrage zu verarbeiten und eine angemessene Antwort zu liefern.
Wenn wir dies im Kontext von Mensch-Maschine-Anwendungen betrachten, "browserbasiert", wie Skrebbel oben sagt, bedeutet dies, dass die (Web-)Anwendung, die im Browser läuft, ihren Zustand und relevante Informationen bei jeder Anfrage an die REST-APIs im Backend senden muss.
Bedenken Sie dies: Sie haben eine Daten-/Informationsplattform, die über REST-APIs zugänglich ist. Vielleicht haben Sie eine Self-Service-BI-Plattform, die alle Datenwürfel verarbeitet. Aber Sie möchten, dass Ihre (menschlichen) Kunden über (1) eine Web-App, (2) eine mobile App und (3) eine Anwendung eines Drittanbieters darauf zugreifen. Letztendlich führt auch die Kette der MTMs zum HTM - richtig. Die menschlichen Nutzer bleiben also an der Spitze der Informationskette.
In den ersten beiden Fällen handelt es sich um eine Interaktion zwischen Mensch und Maschine, d. h. die Informationen werden tatsächlich von einem menschlichen Nutzer konsumiert. Im letzten Fall ist es ein Maschinenprogramm, das die REST-APIs nutzt.
Das Konzept der Authentifizierung gilt für alle Bereiche. Wie werden Sie dies gestalten, damit der Zugriff auf Ihre REST-APIs auf einheitliche, sichere Weise erfolgt? So wie ich das sehe, gibt es 2 Möglichkeiten:
Weg-1:
- Es gibt zunächst einmal keine Anmeldung. Jede Anfrage führt die Anmeldung durch
- Der Client sendet seine identifizierenden Parameter + die anfragespezifischen Parameter mit jeder Anfrage
- Die REST-API nimmt sie, dreht sich um, pingt den Benutzerspeicher (was auch immer das ist) und bestätigt die Autorisierung
- Wenn die Autorisierung hergestellt ist, wird die Anfrage bearbeitet; andernfalls wird sie abgelehnt mit dem entsprechenden HTTP-Statuscode
- Wiederholen Sie die obigen Schritte für jede Anfrage für alle REST-APIs in Ihrer Katalog
Weg-2:
- Der Client beginnt mit einer Authentifizierungsanfrage
- Eine Anmelde-REST-API wird alle derartigen Anfragen bearbeiten
- Es nimmt Authentifizierungsparameter (API-Schlüssel, uid/pwd oder was auch immer Sie wählen) und überprüft die Autorisierung anhand des Benutzerspeichers (LDAP, AD oder MySQL DB usw.)
- Wenn er verifiziert ist, erstellt er ein Authentifizierungs-Token und übergibt es an die Kunden/Anrufer
- Der Aufrufer sendet dann dieses Auth-Token + anfragespezifische Parameter mit jeder nachfolgenden Anfrage an andere REST-APIs des Unternehmens, bis er sich abmeldet oder der Vertrag abläuft
Es ist klar, dass die REST-APIs in Way-2 eine Möglichkeit brauchen, um das Token als gültig zu erkennen und ihm zu vertrauen. Die Login-API hat die Authentifizierungsprüfung durchgeführt, und daher muss dieser "Valet Key" von anderen REST-APIs in Ihrem Katalog als vertrauenswürdig eingestuft werden.
Das bedeutet natürlich, dass der Autorisierungsschlüssel/Token gespeichert und von den REST-APIs gemeinsam genutzt werden muss. Dieser gemeinsame, vertrauenswürdige Token-Speicher kann lokal/verbunden sein, so dass REST-APIs aus anderen Organisationen einander vertrauen können.
Aber ich schweife ab.
Der Punkt ist, dass ein "Status" (über den Authentifizierungsstatus des Kunden) beibehalten und gemeinsam genutzt werden muss, damit alle REST-APIs einen Vertrauenskreis bilden können. Wenn wir dies nicht tun, was der Weg-1 ist, müssen wir akzeptieren, dass ein Authentifizierungsvorgang für alle eingehenden Anfragen durchgeführt werden muss.
Die Durchführung der Authentifizierung ist ein ressourcenintensiver Prozess. Stellen Sie sich vor, dass Sie bei jeder eingehenden Anfrage SQL-Abfragen für Ihren Benutzerspeicher ausführen, um eine uid/pwd-Übereinstimmung zu prüfen. Oder verschlüsseln Sie und führen Sie Hash-Abgleiche durch (wie bei AWS). Und architektonisch gesehen muss jede REST-API dies, so vermute ich, über einen gemeinsamen Back-End-Anmeldedienst durchführen. Denn wenn man das nicht tut, dann verstreut man den Authentifizierungscode überall. Ein großes Durcheinander.
Je mehr Schichten, desto länger die Latenz.
Nehmen Sie nun Weg-1 und wenden Sie ihn auf HTM an. Ist es für Ihren (menschlichen) Benutzer wirklich wichtig, ob Sie bei jeder Anfrage uid/pwd/hash oder was auch immer senden müssen? Nein, solange Sie ihn nicht damit belästigen, dass Sie jede Sekunde die Authentifizierungs-/Login-Seite aufrufen. Viel Glück dabei, Kunden zu haben, wenn Sie das tun. Was Sie also tun werden, ist, die Anmeldeinformationen irgendwo auf der Client-Seite, im Browser, gleich zu Beginn zu speichern und sie bei jeder Anfrage zu senden. Für den (menschlichen) Benutzer ist er bereits eingeloggt, und eine "Sitzung" ist vorhanden. Aber in Wirklichkeit wird er bei jeder Anfrage authentifiziert.
Dasselbe gilt für Weg-2. Ihr (menschlicher) Benutzer wird es nie bemerken. Es wurde also kein Schaden angerichtet.
Was passiert, wenn wir Way-1 auf MTM anwenden? In diesem Fall, da es sich um eine Maschine handelt, können wir diesen Kerl verdammt langweilen, indem wir ihn auffordern, bei jeder Anfrage Authentifizierungsinformationen zu übermitteln. Das kümmert niemanden! Die Anwendung von Weg-2 auf MTM wird keine besondere Reaktion hervorrufen; es ist eine verdammte Maschine. Es könnte sie weniger interessieren!
Die Frage ist also wirklich, was Ihren Bedürfnissen entspricht. Die Staatenlosigkeit hat ihren Preis. Zahlen Sie den Preis und gehen Sie weiter. Wenn Sie ein Purist sein wollen, dann zahlen Sie auch den Preis dafür und ziehen Sie weiter.
Letztendlich spielen Philosophien keine Rolle. Worauf es wirklich ankommt, ist die Suche nach Informationen, ihre Präsentation und das Nutzungserlebnis. Wenn die Menschen Ihre APIs lieben, haben Sie Ihre Aufgabe erfüllt.
Hier ist eine echte und vollständige RESTful-Authentifizierungslösung:
-
Erstellen Sie ein öffentliches/privates Schlüsselpaar auf dem Authentifizierungsserver.
-
Verteilen Sie den öffentlichen Schlüssel an alle Server.
-
Wenn sich ein Client authentifiziert:
3.1. ein Token ausstellen, das Folgendes enthält:
- Verfallszeit
- Name des Benutzers (optional)
- Benutzer IP (optional)
- Hash eines Kennworts (optional)
3.2. Verschlüsseln Sie das Token mit dem privaten Schlüssel.
3.3. Senden Sie das verschlüsselte Token an den Benutzer zurück.
-
Wenn der Nutzer auf eine API zugreift, muss er auch sein Authentifizierungs-Token angeben.
-
Server können überprüfen, ob das Token gültig ist, indem sie es mit dem öffentlichen Schlüssel des Authentifizierungsservers entschlüsseln.
Dies ist eine zustandslose/RESTful-Authentifizierung.
Wenn ein Passwort-Hash enthalten wäre, würde der Benutzer auch das unverschlüsselte Passwort zusammen mit dem Authentifizierungs-Token senden. Der Server könnte durch den Vergleich von Hashes überprüfen, ob das Kennwort mit dem Kennwort übereinstimmt, das zur Erstellung des Authentifizierungstokens verwendet wurde. Eine sichere Verbindung mit HTTPS oder ähnlichem wäre notwendig. Javascript auf der Client-Seite könnte das Passwort des Benutzers abrufen und auf der Client-Seite speichern, entweder im Speicher oder in einem Cookie, möglicherweise verschlüsselt mit dem serverseitigen öffentlich Schlüssel.
Um ehrlich zu sein, habe ich hier großartige Antworten gesehen, aber etwas, das mich stört, ist, wenn jemand das ganze Konzept der Staatenlosigkeit auf die Spitze treibt, so dass es dogmatisch wird. Das erinnert mich an die alten Smalltalk-Fans, die nur reines OO wollten, und wenn etwas kein Objekt ist, dann macht man es falsch. Jetzt mal halblang.
Der RESTful-Ansatz soll Ihnen das Leben erleichtern und den Overhead und die Kosten von Sitzungen reduzieren. Versuchen Sie, ihn zu befolgen, denn es ist eine kluge Sache, aber in dem Moment, in dem Sie eine Disziplin (irgendeine Disziplin/Richtlinie) bis zum Äußersten verfolgen, wo sie nicht mehr den Nutzen bringt, für den sie gedacht war, dann machen Sie es falsch. Einige der besten Sprachen haben heute beides: funktionale Programmierung und Objektorientierung.
Wenn Sie Ihr Problem am einfachsten lösen können, indem Sie den Authentifizierungsschlüssel in einem Cookie speichern und als HTTP-Header senden, dann tun Sie das, aber missbrauchen Sie es nicht. Denken Sie daran, dass Sitzungen schlecht sind, wenn sie schwer und groß werden. Wenn alles, woraus Ihre Sitzung besteht, eine kurze Zeichenkette ist, die einen Schlüssel enthält, was ist dann so schlimm daran?
Ich bin offen für Korrekturen in den Kommentaren, aber ich sehe (bisher) keinen Sinn darin, uns das Leben schwer zu machen, nur um zu vermeiden, dass wir ein großes Wörterbuch mit Hashes auf unserem Server haben.
- See previous answers
- Weitere Antworten anzeigen
4 Stimmen
Wenn ich Restful Authentication google, finde ich ein Dutzend RoR-Plugins. Ich nehme an, dass diese NICHT das sind, wonach Sie suchen. Wenn nicht RoR, welche Sprache dann? Welcher Webserver?
3 Stimmen
Wenn Sie HTTPS verwenden, kann nichts Schlimmes passieren. Die gesamte HTTP-Anfrage wird zusammen mit der URL verschlüsselt.
5 Stimmen
@BharatKhatri: Ja, das würde es. Ich würde niemals sensible Informationen in der für den Benutzer sichtbaren URL weitergeben. Es ist viel wahrscheinlicher, dass diese Informationen zu praktischen Zwecken durchsickern. HTTPS kann bei einem versehentlichen Durchsickern nicht helfen.
3 Stimmen
@jcoffland: Was meinen Sie mit echter RESTful-Authentifizierung? Ich bin interessiert, weil ich gerade den dritten Weg aus der akzeptierten Antwort implementiert habe, aber ich bin nicht glücklich damit (ich mag den zusätzlichen Parameter in der URL nicht).
5 Stimmen
Einige Leute benutzen jwt.io/einfuehrung um dies zu lösen Ich recherchiere gerade darüber, um meinen Fall zu lösen: stackoverflow.com/questions/36974163/ >>Hoffentlich funktioniert das gut.