it-swarm.com.de

Sichern der REST API, ohne das Rad neu zu erfinden

Wenn Sie REST API entwerfen, ist es üblich, einen Benutzer zuerst zu authentifizieren?

Der typische Anwendungsfall, den ich suche, ist:

  • Benutzer möchte Daten erhalten. Klar geil teilen wir gerne! Holen Sie sich einen öffentlichen API-Schlüssel und lesen Sie ihn weg!
  • Benutzer möchte Daten speichern/aktualisieren ... woah, warte! Wer bist du, kannst du das tun?

Ich möchte es einmal erstellen und beispielsweise einer Web-App, einer Android Anwendung oder einer iPhone-Anwendung erlauben, es zu verwenden.

Eine REST API scheint bei solchen Anforderungen eine logische Wahl zu sein

Um meine Frage zu veranschaulichen, verwende ich ein einfaches Beispiel.

Ich habe einen Artikel in einer Datenbank, der ein Bewertungsattribut hat (Ganzzahl 1 bis 5).

Wenn ich REST richtig verstehe, würde ich eine GET-Anfrage in der Sprache meiner Wahl implementieren, die csv, xml oder json wie folgt zurückgibt:

http://example.com/product/getrating/{id}/

Angenommen, wir wählen JSON, das wir zurückgeben:

{
  "id": "1",
  "name": "widget1",
  "attributes": { "rating": {"type":"int", "value":4} }
}

Dies ist in Ordnung für öffentlich zugängliche APIs. Ich verstehe diesen Teil.

Wo ich Unmengen von Fragen habe, ist, wie ich dies mit einem Sicherheitsmodell kombiniere? Ich bin an die Sicherheit von Webanwendungen gewöhnt, bei denen ich einen Sitzungsstatus habe, der meinen Benutzer jederzeit identifiziert, damit ich steuern kann, was er tun kann, unabhängig davon, für was er sich entscheidet, mich zu senden. So wie ich es verstehe, ist das nicht RESTful, also wäre es eine schlechte Lösung in diesem Fall.

Ich werde versuchen, ein anderes Beispiel mit demselben Artikel/derselben Bewertung zu verwenden.

Wenn Benutzer "JOE" eine Bewertung zu einem Element hinzufügen möchte

Dies könnte geschehen mit:

http://example.com/product/addrating/{id}/{givenRating}/

An dieser Stelle möchte ich die Daten speichern, die besagen, dass "JOE" dem Produkt {id} eine Bewertung von {givenRating} gegeben hat.

Frage: Woher weiß ich, dass die Anfrage von "JOE" und nicht von "BOB" kam?.

Was wäre, wenn es sich um sinnvollere Daten wie die Telefonnummer eines Benutzers handeln würde?

Was ich bisher habe, ist:

1) Verwenden Sie die integrierte Funktion von HTTP, um sich bei jeder Anforderung zu authentifizieren, entweder bei einfachem HTTP oder bei HTTPS.

Dies bedeutet, dass jede Anfrage jetzt die Form von:

https://joe:[email protected]/product/addrating/{id}/{givenRating}/

2) Verwenden Sie einen Ansatz wie Amazon S3 mit privatem und öffentlichem Schlüssel: http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

3) Verwenden Sie trotzdem ein Cookie und unterbrechen Sie den zustandslosen Teil von REST.

Der zweite Ansatz erscheint mir besser, aber ich frage mich, ob ich das Ganze wirklich neu erfinden muss. Hashing, Speichern, Generieren der Schlüssel, etc. ganz alleine?

Das klingt nach einer Sitzung in einer typischen Webanwendung, in der Sie den gesamten Stapel selbst neu schreiben. Dies bedeutet für mich normalerweise "Sie machen es falsch", insbesondere wenn Sie mit Sicherheit zu tun haben.

EDIT: Ich denke, ich hätte auch OAuth erwähnen sollen.

73
jfrobishow

Edit 5 Jahre später

Benutze OAuth2!

Vorgängerversion

Nein, es ist absolut nicht erforderlich, ein Cookie zu verwenden. Es ist nicht halb so sicher wie HTTP Digest, OAuth oder Amazon AWS (was nicht schwer zu kopieren ist).

Die Art und Weise, wie Sie ein Cookie betrachten sollten, ist, dass es sich um ein Authentifizierungstoken handelt, das genauso viel wie Basic/Digest/OAuth/ist, je nachdem, was auch immer, aber weniger geeignet ist.

Ich habe jedoch nicht das Gefühl, dass die Verwendung eines Cookies per se gegen REST-Prinzipien verstößt , solange der Inhalt des Sitzungscookies keinen Einfluss auf den Inhalt von hat Die Ressource, die Sie vom Server zurückgeben.

Cookies sind böse, hör auf, sie zu verwenden.

21
Evert

Machen Sie sich keine Sorgen um "RESTful", sorgen Sie sich nicht um die Sicherheit. So mache ich es:

Schritt 1: Benutzer greift mit Anmeldeinformationen auf den Authentifizierungsdienst zu.

Schritt 2: Wenn Anmeldeinformationen ausgecheckt werden, geben Sie einen Fingerabdruck, eine Sitzungs-ID usw. zurück und speichern Sie sie im gemeinsam genutzten Speicher, um sie später schnell abzurufen, oder verwenden Sie eine Datenbank, wenn es Ihnen nichts ausmacht, die Bearbeitungszeit Ihres Webdienstes um einige Millisekunden zu verlängern .

Schritt 3: Fügen Sie oben in jedem Webservice-Skript einen Einstiegspunktaufruf hinzu, der den Fingerabdruck und die Sitzungs-ID für every Webservice-Anforderung überprüft.

Schritt 4: Wenn der Fingerabdruck und die Sitzungs-ID nicht gültig sind oder das Zeitlimit überschritten wurde, leiten Sie zur Authentifizierung um.

LESEN SIE DIES:

RESTful Authentication

21
Daniel Pereira

3 Jahre später bearbeiten

Ich stimme voll und ganz mit Evert überein, benutze OAuth2 mit HTTPS und erfinde das Rad nicht neu! :-)

Durch einfachere REST APIs - nicht für Clients von Drittanbietern gedacht - kann JSON Web Tokens ebenfalls gut sein.

Vorherige Version

Verwenden Sie trotzdem ein Cookie und unterbrechen Sie den zustandslosen Teil von REST.

Verwenden Sie keine Sitzungen, da Ihr REST - Dienst in Sitzungen nicht gut skalierbar ist. Hier gibt es zwei Zustände: Anwendungsstatus (oder Clientstatus oder Sitzungsstatus) und Ressourcenstatus. Der Anwendungsstatus enthält die Sitzungsdaten und wird vom Client REST verwaltet. Der Ressourcenzustand enthält die Ressourceneigenschaften und -beziehungen und wird vom Dienst REST verwaltet. Sie können sehr einfach entscheiden, ob eine bestimmte Variable Teil des Anwendungsstatus oder des Ressourcenzustands ist. Wenn die Datenmenge mit der Anzahl der aktiven Sitzungen zunimmt, gehört dies zum Anwendungsstatus. So gehört beispielsweise die Benutzeridentität der aktuellen Sitzung zum Anwendungsstatus, aber die Liste der Benutzer oder Benutzerberechtigungen gehört zum Ressourcenstatus.

Der Client REST sollte daher die Identifikationsfaktoren speichern und sie bei jeder Anforderung senden. Verwechseln Sie den Client REST nicht mit dem HTTP-Client. Sie sind nicht gleich. Der Client REST kann sich auch auf der Serverseite befinden, wenn er Curl verwendet, oder er kann beispielsweise ein serverseitiges HTTP-Only-Cookie erstellen, das er über CORS mit dem Dienst REST teilen kann. Das Einzige, was zählt, ist, dass sich der REST - Dienst bei jeder Anforderung authentifiziert, sodass Sie die Anmeldeinformationen (Benutzername, Kennwort) bei jeder Anforderung senden müssen.

  • Wenn Sie einen clientseitigen REST Client schreiben, kann dies mit SSL + HTTP-Authentifizierung erfolgen. In diesem Fall können Sie einen credentials -> (identity, permissions) - Cache auf dem Server erstellen, um die Authentifizierung zu beschleunigen. Beachten Sie, dass, wenn Sie diesen Cache leeren und die Benutzer dieselbe Anforderung senden, sie dieselbe Antwort erhalten, dies jedoch etwas länger dauert. Sie können dies mit Sitzungen vergleichen: Wenn Sie den Sitzungsspeicher löschen, erhalten Benutzer eine Antwort status: 401 unauthorized ...
  • Wenn Sie einen serverseitigen REST Client schreiben und Identifikationsfaktoren per Curl an den REST Service senden, haben Sie zwei Möglichkeiten. Sie können auch http auth verwenden oder einen Sitzungsmanager in Ihrem REST - Client verwenden, jedoch nicht im REST - Dienst.
  • Wenn ein nicht vertrauenswürdiger Benutzer Ihren REST - Client schreibt, müssen Sie eine Anwendung schreiben, um die Benutzer zu authentifizieren und ihnen die Verfügbarkeit zu geben, damit sie entscheiden können, ob sie verschiedenen Clients Berechtigungen erteilen möchten oder nicht. Oauth ist dafür eine bereits vorhandene Lösung. Oauth1 ist sicherer, Oauth2 ist weniger sicher, aber einfacher, und ich denke, es gibt mehrere andere Lösungen für dieses Problem ... Sie müssen dies nicht neu erfinden. Es gibt vollständige Authentifizierungs- und Autorisierungslösungen, die oauth verwenden, zum Beispiel: wso identity server .

Cookies sind nicht unbedingt schlecht. Sie können sie auf REST-konforme Weise verwenden, bis sie den Clientstatus und der Service nur den Ressourcenstatus enthalten. Zum Beispiel können Sie den Einkaufswagen oder die bevorzugten Paginierungseinstellungen in Cookies speichern ...

8
inf3rno