Ich entwerfe einen RESTful-Webdienst, auf den Benutzer, aber auch andere Webdienste und -anwendungen zugreifen müssen. Alle eingehenden Anforderungen müssen authentifiziert werden. Die gesamte Kommunikation erfolgt über HTTPS. Die Benutzerauthentifizierung funktioniert basierend auf einem Authentifizierungstoken, das durch POSTEN des Benutzernamens und des Kennworts (über eine SSL-Verbindung) an eine vom Dienst bereitgestellte / Sitzungsressource erworben wurde .
Bei Webdienst-Clients steht hinter dem Client-Dienst kein Endbenutzer . Die Anforderungen werden durch geplante Aufgaben, Ereignisse oder andere Computeroperationen ausgelöst. Die Liste der Verbindungsdienste ist im Voraus bekannt (offensichtlich, denke ich). Wie soll ich diese Anfragen von anderen (Web-) Diensten authentifizieren? Ich möchte, dass der Authentifizierungsprozess für diese Dienste so einfach wie möglich implementiert wird, jedoch nicht auf Kosten der Sicherheit. Was wären die Standard- und Best Practices für ein solches Szenario?
Optionen, an die ich denken kann (oder die mir vorgeschlagen wurden):
Lassen Sie die Client-Dienste auf einen "falschen" Benutzernamen und ein falsches Kennwort zurückgreifen und authentifizieren Sie sie auf die gleiche Weise wie Benutzer. Ich mag diese Option nicht - sie fühlt sich einfach nicht richtig an.
Weisen Sie dem Client-Service eine permanente Anwendungs-ID zu, möglicherweise auch einen Anwendungsschlüssel. Soweit ich verstanden habe, ist dies genau das Gleiche wie Benutzername + Passwort. Mit dieser ID und diesem Schlüssel kann ich entweder jede Anforderung authentifizieren oder ein Authentifizierungstoken erstellen, um weitere Anforderungen zu authentifizieren. In beiden Fällen gefällt mir diese Option nicht, da jeder, der die Anwendungs-ID und den Schlüssel erhalten kann, sich als Client ausgeben kann.
Ich könnte der vorherigen Option eine IP-Adressprüfung hinzufügen. Dies würde es schwieriger machen, gefälschte Anfragen auszuführen.
Client-Zertifikate. Richten Sie meine eigene Zertifizierungsstelle ein, erstellen Sie ein Stammzertifikat und erstellen Sie Clientzertifikate für die Clientdienste. Es fallen jedoch einige Probleme ein: a) Wie erlaube ich den Benutzern immer noch, sich ohne Zertifikate zu authentifizieren, und b) wie kompliziert ist die Implementierung dieses Szenarios aus Sicht des Client-Service?
Noch etwas - es muss andere Lösungen geben?
Mein Dienst würde auf Java ausgeführt, aber ich habe bewusst Informationen darüber ausgelassen, auf welchem spezifischen Framework er aufbauen würde, da ich mich mehr für die Grundprinzipien und nicht so sehr für die Implementierungsdetails interessiere - ich gehe von der besten Lösung für diesen Willen aus unabhängig vom zugrunde liegenden Framework implementiert werden können. Ich bin jedoch etwas unerfahren mit diesem Thema, daher werden auch konkrete Tipps und Beispiele zur tatsächlichen Implementierung (wie nützliche Bibliotheken, Artikel usw. von Drittanbietern) sehr geschätzt.
Antworten:
Jede Lösung für dieses Problem läuft auf ein gemeinsames Geheimnis hinaus. Ich mag auch die fest codierte Option für Benutzername und Passwort nicht, aber sie hat den Vorteil, dass sie recht einfach ist. Das Client-Zertifikat ist auch gut, aber ist es wirklich viel anders? Es gibt ein Zertifikat auf dem Server und eines auf dem Client. Der Hauptvorteil ist, dass es schwieriger ist, Gewalt anzuwenden. Hoffentlich haben Sie andere Schutzmaßnahmen, um sich dagegen zu schützen.
Ich denke nicht, dass Ihr Punkt A für die Client-Zertifikat-Lösung schwer zu lösen ist. Sie verwenden nur einen Zweig.
if (client side certificat) { check it } else { http basic auth }
Ich bin kein Java-Experte und habe noch nie damit gearbeitet, um clientseitige Zertifikate zu erstellen. Ein schnelles Google führt uns jedoch zu diesem Tutorial, das genau in Ihrer Gasse nachschaut.Lassen Sie mich trotz all dieser "Was ist das Beste" -Diskussion nur darauf hinweisen, dass es eine andere Philosophie gibt, die besagt: "Weniger Code, weniger Klugheit ist besser." (Ich persönlich halte diese Philosophie). Die Client-Zertifikat-Lösung klingt nach viel Code.
Ich weiß, dass Sie Fragen zu OAuth geäußert haben, aber der OAuth2-Vorschlag enthält eine Lösung für Ihr Problem namens " Bearer Token ", die in Verbindung mit SSL verwendet werden muss. Ich denke, der Einfachheit halber würde ich entweder den fest codierten Benutzer / Pass (einen pro App, damit sie einzeln widerrufen werden können) oder die sehr ähnlichen Inhaber-Token wählen.
quelle
Nachdem Sie Ihre Frage gelesen haben, würde ich sagen, generieren Sie ein spezielles Token, um die erforderlichen Anforderungen zu erfüllen. Dieser Token wird in einer bestimmten Zeit leben (sagen wir an einem Tag).
Hier ist ein Beispiel zum Generieren eines Authentifizierungstokens:
Zum Beispiel: 3. Juni 2011
dann mit dem Benutzerkennwort verketten, Beispiel "my4wesomeP4ssword!"
Führen Sie dann MD5 dieser Zeichenfolge aus:
Wenn Sie eine Anfrage aufrufen, verwenden Sie immer dieses Token.
Dieses Token ist jeden Tag einzigartig. Ich denke, diese Art von Schutz ist mehr als ausreichend, um Ihren Service immer zu schützen.
Hoffnung hilft
:) :)
quelle
Es gibt verschiedene Ansätze.
Die RESTful-Puristen möchten, dass Sie die BASIC-Authentifizierung verwenden und bei jeder Anforderung Anmeldeinformationen senden. Ihre Begründung ist, dass niemand einen Staat speichert.
Der Clientdienst kann ein Cookie speichern, das eine Sitzungs-ID verwaltet. Ich persönlich finde das nicht so beleidigend wie einige der Puristen, von denen ich höre - es kann teuer sein, sich immer wieder zu authentifizieren. Es hört sich jedoch so an, als ob Sie diese Idee nicht besonders mögen.
Aus Ihrer Beschreibung geht hervor, dass Sie sich vielleicht für OAuth2 interessieren. Meine bisherige Erfahrung zeigt, dass es verwirrend und blutig ist. Es gibt Implementierungen, aber es gibt nur wenige. Ich verstehe, dass es in Java in die Sicherheitsmodule von Spring3 integriert wurde . (Ihr Tutorial ist gut geschrieben.) Ich habe darauf gewartet, ob es eine Erweiterung in Restlet geben wird , aber bisher wurde sie, obwohl sie vorgeschlagen wurde und sich möglicherweise im Inkubator befindet, noch nicht vollständig integriert.
quelle
Ich glaube der Ansatz:
ist ziemlich Standard, unabhängig davon, wie Sie implementieren und andere spezifische technische Details.
Wenn Sie den Umschlag wirklich verschieben möchten, können Sie möglicherweise den https-Schlüssel des Clients in einem vorübergehend ungültigen Zustand betrachten, bis die Anmeldeinformationen validiert sind, Informationen einschränken, falls dies niemals der Fall ist, und den Zugriff gewähren, wenn sie validiert werden, basierend auf dem Ablauf.
Hoffe das hilft
quelle
Was den Client-Zertifikat-Ansatz angeht, wäre die Implementierung nicht besonders schwierig, während die Benutzer ohne Client-Zertifikate weiterhin zugelassen werden.
Wenn Sie tatsächlich Ihre eigene selbstsignierte Zertifizierungsstelle erstellt und Client-Zertifikate für jeden Client-Service ausgestellt hätten, hätten Sie eine einfache Möglichkeit, diese Services zu authentifizieren.
Abhängig von dem von Ihnen verwendeten Webserver sollte es eine Methode zum Angeben der Clientauthentifizierung geben, die ein Clientzertifikat akzeptiert, jedoch keine erfordert. In Tomcat können Sie beispielsweise bei der Angabe Ihres https-Connectors 'clientAuth = want' anstelle von 'true' oder 'false' festlegen. Sie würden dann sicherstellen, dass Sie Ihr selbstsigniertes CA-Zertifikat zu Ihrem Truststore hinzufügen (standardmäßig die Cacerts-Datei in der von Ihnen verwendeten JRE, sofern Sie in Ihrer Webserver-Konfiguration keine andere Datei angegeben haben), sodass die einzigen vertrauenswürdigen Zertifikate diejenigen sind, die von ausgestellt wurden Ihre selbstsignierte Zertifizierungsstelle.
Auf der Serverseite würden Sie den Zugriff auf die Dienste, die Sie schützen möchten, nur zulassen, wenn Sie in der Lage sind, ein Clientzertifikat aus der Anforderung abzurufen (nicht null), und alle DN-Prüfungen bestehen, wenn Sie zusätzliche Sicherheit bevorzugen. Benutzer ohne Client-Zertifikate können weiterhin auf Ihre Dienste zugreifen, haben jedoch einfach keine Zertifikate in der Anforderung.
Meiner Meinung nach ist dies der "sicherste" Weg, aber er hat sicherlich seine Lernkurve und seinen Overhead und ist daher möglicherweise nicht unbedingt die beste Lösung für Ihre Bedürfnisse.
quelle
5. Noch etwas - es muss andere Lösungen geben?
Du hast recht, das gibt es! Und es heißt JWT (JSON Web Tokens).
JSON Web Token (JWT) ist ein offener Standard (RFC 7519), der eine kompakte und in sich geschlossene Methode zur sicheren Übertragung von Informationen zwischen Parteien als JSON-Objekt definiert. Diese Informationen können überprüft und als vertrauenswürdig eingestuft werden, da sie digital signiert sind. JWTs können mit einem geheimen (mit dem HMAC-Algorithmus) oder einem öffentlichen / privaten Schlüsselpaar mit RSA signiert werden.
Ich empfehle dringend, sich mit JWTs zu befassen. Sie sind eine viel einfachere Lösung für das Problem im Vergleich zu alternativen Lösungen.
https://jwt.io/introduction/
quelle
Sie können eine Sitzung auf dem Server erstellen
sessionId
und bei jedem REST-Aufruf zwischen Client und Server freigeben.Erste REST-Anfrage authentifizieren :
/authenticate
. Gibt die Antwort (gemäß Ihrem Client-Format) mit zurücksessionId: ABCDXXXXXXXXXXXXXX
.Speichern Sie dies
sessionId
in derMap
aktuellen Sitzung.Map.put(sessionid, session)
oder verwenden SieSessionListener
, um Schlüssel für Sie zu erstellen und zu zerstören;Holen Sie sich bei jedem REST-Aufruf eine Sitzungs-ID, wie
URL?jsessionid=ABCDXXXXXXXXXXXXXX
(oder auf andere Weise);HttpSession
von der Karte mitsessionId
;quelle
Ich würde eine Anwendung verwenden lassen, die einen Benutzer mit einem Anwendungs-ID-Parameter auf Ihre Site umleitet. Sobald der Benutzer die Anforderung genehmigt, wird ein eindeutiges Token generiert, das von der anderen App zur Authentifizierung verwendet wird. Auf diese Weise verarbeiten die anderen Anwendungen keine Benutzeranmeldeinformationen, und andere Anwendungen können von Benutzern hinzugefügt, entfernt und verwaltet werden. Foursquare und einige andere Sites authentifizieren sich auf diese Weise und sind sehr einfach als andere Anwendung zu implementieren.
quelle
Neben der Authentifizierung schlage ich vor, dass Sie über das Gesamtbild nachdenken. Machen Sie Ihren Backend-RESTful-Service ohne Authentifizierung. Stellen Sie dann einen sehr einfachen, für die Authentifizierung erforderlichen Middle Layer-Dienst zwischen den Endbenutzer und den Backend-Dienst.
quelle