2017-02-16 3 views
10

Ich schreibe einen REST-Client in Java mit dem HttpClient, die REST-API, auf die ich zugreife, benötigt ein Authentifizierungs-Token für jede REST-Aktion. Dieser Token ist 24 Stunden lang gültig.Best Practices zum Verwalten von Authentifizierungs-Token

Die Art, wie ich das jetzt handle, ruft eine "getAuth()" -Methode auf, immer wenn ich einen REST-Aufruf machen muss, der wie ein Overhead auf dem Auth-Server erscheint.

Wie kann ich dieses Authentifizierungs-Token bequem speichern und seinen Lebenszyklus verwalten? Gibt es dokumentierte Best Practices?

Ich dachte an die folgende Lösung

public class MySession { 
    String user; 
    String pass; 
    public MySession(String user, String pass) { 
     this.user = user; 
     this.pass = pass; 
    } 

    public getAuth() { 
     //user user, pass to get auth token 
    } 
} 

und übergeben dann die Sitzungen zu jeder Klasse-Objekt, die das Token nees. Wenn das Token abgelaufen ist, rufen Sie einfach diese Methode erneut

+0

Wie ist Ihr Kunde? Ist es eine Java-Anwendung? Haben Sie Bedenken, das Token auf Client- oder Serverseite zu speichern? –

+0

Es ist eine Java-Dropwizard-Anwendung, ich mache mir Sorgen über das Speichern des Tokens in der Datenbank und machen zu viele db-Aufrufe, stattdessen sollte ich mit dem Token bis er abläuft und dann ein neues anfordern (wenn es ein "Token abgelaufen" wirft Ausnahme oder etwas .. –

+0

Können Sie bitte Ihren Client-Code anzeigen? Auf der Clientseite könnten Sie einen Cache im Speicher verwenden, wenn das Speichern des Tokens in der Datenbank zu Leistungsproblemen führen könnte.Wenn Sie wissen, dass das Token abläuft und Sie es aktualisieren können, tun Sie es einfach :) –

Antwort

2

Wenn Sie sich Sorgen über zu viele Treffer in der Datenbank machen, dann nehme ich an, es gibt eine Menge Web-Aktivität.

Ich würde nicht empfehlen, Session in Ihrem Fall zu verwenden, sondern speichern Sie das Token in einem Cookie auf dem Client.

In einer Umgebung mit hohem Datenverkehr (von der ich annahm, dass sie gehört), kann die Verwendung von Session viel Serverspeicher belegen, und die Skalierbarkeit kann ebenfalls ein Problem sein, da Sitzungen in einem Cluster synchronisiert bleiben müssen.

Als @ Cássio Mazzochi Molin auch erwähnt, können Sie einen In-Memory-Cache verwenden, um alle benutzerspezifischen Daten und Tokens zu speichern. Dadurch werden die Zugriffe auf die Datenbank reduziert und Sie können die Anwendung einfacher skalieren, wenn dies erforderlich ist.

2

Der de-facto-Standard wird eine eigene Lösung nicht Umsetzung (Grundregel in Sicherheit: Sie Ihre eigenen Sachen nicht implementieren!), Aber die de-facto-Standard-Lösung verwenden, nämlich JSON Web Tokens.

Dokumentation auf der Website, aber die Grundidee ist, dass Sie nur einen Wert (den privaten Schlüssel des Servers) speichern müssen, und dann können Sie jeden ursprünglich vom Server ausgegebenen Anspruch überprüfen (der in Ihrem Fall enthalten wird) eine Ablaufzeit).

0

Verwenden Sie Json Web-Token, um Informationen zwischen zwei Clients auszutauschen. Der Token wird nur für die 24 Stunden am Leben bleiben, danach werden alle Folgeaufrufe in der Kopfzeile zurückgewiesen.

2

Der Kürze halber nehme ich an, dass Sie einen Endpunkt anrufen, den Sie nicht ändern können. Die Art der Implementierung hängt stark davon ab, ob das Token app- oder benutzerbasiert ist (ein Token für alle Benutzer in einer freigegebenen App-Instanz oder ein Token pro Benutzer).

Wenn es eine Auth-Token für die gesamte App:

  • im Speicher sichert zusammen mit einem Time-to-Live-Zeitstempel (oder alternativ das Token abgelaufenen Fehler abfangen, fordern Sie ein neues Token und die ursprünglichen wiederholen Anfrage), es zu aktualisieren, wenn es nicht vorhanden ist/ist abgelaufen
  • wenn Sie besorgt sind neu anfordernden API-Token nach einem Neustart der Anwendung speichern sie auch in der Datenbank und es beim Start zu laden, wenn es
existiert

Wenn es ein Token pro Benutzer ist:

  • Bewahren Sie es in Ihrer Benutzersitzung, es ist genau das, was Sitzungen für verwendet werden, wenn Benutzer sind authing dann werden sie eine Sitzung haben und der Aufwand ist schon da
  • Wenn Sie nicht wollen, ein Zeichen jedes Mal sie speichern anmelden ihre aktuelle Token in der DB Wiederanforderung und und in ihre Sitzung laden, wenn sie
+0

Hallo Dave, das ist eine sehr treffende Antwort. Vielen Dank. Dies ist ein Authentifizierungs-Token für die gesamte App. Mein ursprünglicher Ansatz bestand darin, das Token weiterhin zu verwenden und dann die Ausnahme abzufangen, um ein neues Token anzufordern. Mit diesem werde ich jeden REST-Aufruf für die Ausnahme beobachten. Ist das eine gute Übung? Auch, wenn ich jeden REST-Anruf beobachte, wie beeinflusst das Attribut "Time to Live" den Unterschied? Fordern Sie auch das Token (das erste) beim Start der Anwendung an? –

+0

Entschuldigung für die verzögerte Antwort - Sie brauchen keine Zeit zu leben, wenn Sie die Ausnahme abfangen und die Anfrage nach Erhalt eines neuen Tokens erneut abspielen. Sie sollten sowieso jeden Anruf für Ausnahmen beobachten, es gibt im Grunde keine Overhead-Verarbeitung und Sie möchten sicherstellen, dass nichts anderes schief geht (und wenn Sie Netzwerkanrufe tun, wird alles und irgendetwas irgendwann schiefgehen). Ich würde das Token anfordern, wenn ich die erste Anfrage machte - kein Punkt, der es früh abfeuert. –

3

anmelden ich schlage vor, Sie das folgende Szenario zu verwenden:

1) Zunächst rufen auth(username, password) Rest api, um den Authentifizierungs-Token zu erhalten. Wenn die angegebenen Anmeldeinformationen in Ordnung sind, senden Sie das Authentifizierungs-Cookie mit dem HTTP 200-Antwortcode an den Client zurück.

2) Dann können Sie geschützte Ruhe apis aufrufen. Sie müssen jedes Mal auth Cookie mit Ihrer Anfrage senden.

3) Servlet-Filter (oder etwas Ähnliches) prüft jede eingehende Anfrage und validiert das Token. Wenn das Token gültig ist, wird die Anforderung an die Restmethode weitergeleitet, andernfalls müssen Sie eine HTTP 401/403-Antwort generieren.

Ich empfehle Ihnen, Ihre eigene Authentifizierungsschicht nicht zu schreiben. Anstatt ein vorhandenes zu installieren und zu verwenden. Ich schlage vor, Sie OpenAM. Es ist ein hervorragendes Open Source Access Management System.

Ich schlage auch vor, dass Sie Sitzung auf der Serverseite für Authentifizierungszwecke nicht öffnen. Wenn Sie 10 Clients haben, müssen 10 Sitzungen vom Server verwaltet werden. Es ist kein großes Problem. Aber wenn Sie 100, 1000 oder Millionen verschiedene Clients haben, benötigen Sie mehr Speicher zum Speichern von Sitzungen auf dem Server.

2

Sie können einen Manager erstellen und den auth-Cookie während der Anmeldung im lokalen Thread speichern, wie im folgenden Code. Sie können den Cookie von getAuth() erhalten, solange der Thread lebt.

public class Manager { 
    private static final ThreadLocal<String> SECURITY_CONTEXT = new ThreadLocal<>(); 

    public static void setAuth(String auth) { 
     SECURITY_CONTEXT.set(auth); 
    } 

    public static String getAuth() { 
     return SECURITY_CONTEXT.get(); 
    } 

    public static void clear(){ 
     SECURITY_CONTEXT.remove(); 
    } 
} 
3

Ich gehe davon aus, dass Sie OAuth für die Autorisierung verwenden. Ob Sie JWT oder andere Tokens verwenden, spielt für diese Situation keine Rolle.

Wenn Genehmigung durchführen Sie eine access_token mit einem Ablauf und je nach Erteilung Art werden Sie anfordern (Client-Anmeldeinformationen, Autorisierungscode, Implicit, Ressourceneigentümer) ausgegeben, eine refresh_token.

Der Client sollte die access_token und das Ablaufdatum behalten. Das refresh_token muss, wenn es ausgegeben wird, geheim gehalten werden (achten Sie darauf, dass Sie die korrekte Berechtigung für Ihren Anwendungsfall verwenden).

In nachfolgenden Aufrufen sollte Ihr Client keine neuen Token bei jedem Aufruf anfordern, er sollte den gespeicherten verwenden.

Sobald die API 401 Unauthorized zurückgibt, ist die access_token wahrscheinlich abgelaufen. Ihr Client sollte versuchen, die access_token mit der refresh_token zu aktualisieren, wenn Sie eine haben. Wenn Sie keine refresh_token haben oder die Aktualisierungsanforderung ebenfalls fehlgeschlagen ist, weil die refresh_token nicht mehr gültig ist, können Sie einen neuen Autorisierungsablauf durchführen.

Sie können die Ablaufzeit als Anhaltspunkt verwenden, um zu wissen, wann Sie eine neue access_token entweder durch Aktualisierung oder durch einen neuen vollständigen Autorisierungsablauf erhalten. Dies vermeidet die 401 Unauthorized. In jedem Fall sollte Ihr Client eine Rückfall-Richtlinie haben, wenn diese Antwort empfangen wird, nachdem für einige Anrufe ein gültiger access_token verwendet wurde.

+0

Ich habe kein Refresh-Token. In diesem Fall sollte ich auf diese Ausnahme achten und das Authentifizierungs-Token erneut setzen? –

+0

Wenn Sie erneut eine '401 Nicht autorisiert'-Funktion erhalten, führen Sie eine neue Autorisierung mit den Anmeldeinformationen durch. Wenn Sie ein wenig optimieren möchten, verwenden Sie auch die Ablaufzeit, um ein neues Token noch vor Ablauf zu verlängern. –

+0

Danke, also werde ich ein "Session" -Objekt bei App-Start mit dem Token und TTL instanziieren und dies an alles weitergeben, das einen REST-Aufruf macht. Wenn ich 401 erhalte, setze ich das neue Token auf dieses Objekt. Richtig? –

2

Sie sollten JsonWebToken (kurz JWT) für diese Art von Sachen verwenden. JWT hat Unterstützung eingebaut, um das Ablaufdatum festzulegen. Es gibt viele Bibliotheken, diese Methode zu verwenden, und Sie können mehr lesen here

Es gibt currenlty 4 Java-Implementierungen und alle von ihnen prüfen, ob das Token noch gültig ist (exp Scheck) enter image description here

2

Also, wenn ich Wenn Sie richtig verstanden haben, verwenden Sie dasselbe Token für alle Ihre Anfragen (das heißt, solange Ihre App läuft und Sie die Token aktualisieren, sollten Sie in Ordnung sein. Ich hatte buchstäblich das gleiche Problem und so habe ich Ich habe eine Singleton-Klasse, die beim Start der App für einmal initialisiert wird und das Token aktualisiert, wenn es ungültig ist. Ich verwende C#, Asp.NET MVC5 und AutoFac für DI, aber ich bin mir sicher, dass Sie das tun können das gleiche mit Java und Spring.

Updating property of a singleton with Thread Safety

-2
  1. Auth-Token für jede Anforderung sind richtiger Ansatz, Betrachten Auth Server Skalierung für Performance-Problem.
  2. Bei der ersten erfolgreichen Authentifizierung (Benutzername und Kennwort) ein privates öffentliches Schlüsselpaar generieren. Speichern private Schlüssel als Session Security Token (SST) und öffentlichen Schlüssel als Public Security Client-Schlüssel (PSCK) zu Client
  3. In all senden fordern andere als Login (oder Authentifizierung) Client PSCK senden Diebstahl von Benutzernamen zu schützen und das Passwort und der Server können PSCK intern in regelmäßigen Abständen verifizieren, wodurch Verarbeitungszeit eingespart wird.
  4. Wenn das System auf der Authentifizierungsseite ein Leistungsproblem hat, installieren Sie den Auth-Server mit Skalierbarkeit.
  5. Kein Token oder Kennwort, das zwischengespeichert, unverschlüsselt ausgetauscht und außerhalb der Sicherheitszone gesendet werden soll. Veröffentlichen Sie keine URL-Parameter.
Verwandte Themen