Wir verwenden Retrofit in unserer Android-App, um mit einem OAuth2-gesicherten Server zu kommunizieren. Alles funktioniert hervorragend. Wir verwenden den RequestInterceptor, um das Zugriffstoken bei jedem Aufruf einzuschließen. Es wird jedoch Zeiten geben, in denen das Zugriffstoken abläuft und das Token aktualisiert werden muss. Wenn das Token abläuft, wird der nächste Aufruf mit einem nicht autorisierten HTTP-Code zurückgegeben, sodass die Überwachung einfach ist. Wir können jeden Retrofit-Aufruf folgendermaßen ändern: Überprüfen Sie im Fehlerrückruf, ob der Fehlercode Unauthorized entspricht, aktualisieren Sie das OAuth-Token und wiederholen Sie den Retrofit-Aufruf. Zu diesem Zweck sollten jedoch alle Anrufe geändert werden, was keine leicht zu wartende und gute Lösung ist. Gibt es eine Möglichkeit, dies zu tun, ohne alle Retrofit-Aufrufe zu ändern?
157
Antworten:
Bitte nicht verwenden
Interceptors
, um mit der Authentifizierung umzugehen.Derzeit ist der beste Ansatz für die Authentifizierung die Verwendung der neuen
Authenticator
API, die speziell für diesen Zweck entwickelt wurde .OkHttp fragt automatisch nach den
Authenticator
Anmeldeinformationen, wenn eine Antwort die401 Not Authorised
letzte fehlgeschlagene Anforderung mit ihnen wiederholt .Befestigen Sie ein
Authenticator
an einem,OkHttpClient
wie Sie es tunInterceptors
Verwenden Sie diesen Client beim Erstellen Ihres
Retrofit
RestAdapter
quelle
TokenAuthenticator
hängt von einerservice
Klasse ab. Dieservice
Klasse hängt von einerOkHttpClient
Instanz ab. Um ein zu erstellen,OkHttpClient
brauche ich dasTokenAuthenticator
. Wie kann ich diesen Zyklus durchbrechen? Zwei verschiedeneOkHttpClient
s? Sie werden verschiedene Verbindungspools haben ...Wenn Sie Retrofit > =
1.9.0
verwenden, können Sie den neuen Interceptor von OkHttp verwenden , der in eingeführt wurdeOkHttp 2.2.0
. Sie möchten einen Application Interceptor verwenden , mit dem Sie dies tun könnenretry and make multiple calls
.Ihr Interceptor könnte ungefähr so aussehen wie dieser Pseudocode:
Nachdem Sie Ihre definiert haben
Interceptor
, erstellen Sie eineOkHttpClient
und fügen Sie den Interceptor als Application Interceptor hinzu .Und schließlich verwenden Sie dies
OkHttpClient
beim Erstellen IhrerRestAdapter
.Warnung: Wie
Jesse Wilson
(von Square) hier erwähnt , ist dies eine gefährliche Menge an Kraft.Angesichts dessen denke ich definitiv, dass dies der beste Weg ist, so etwas jetzt zu handhaben. Wenn Sie Fragen haben, zögern Sie bitte nicht, in einem Kommentar zu fragen.
quelle
Wenn Sie beispielsweise eine Nachrüstung haben
TokenService
, die Sie in IhremAuthenticator
Gerät benötigen, aber nur eine einrichten möchten, für dieOkHttpClient
Sie eineTokenServiceHolder
als Abhängigkeit verwenden könnenTokenAuthenticator
. Sie müssten einen Verweis darauf auf Anwendungsebene (Singleton) pflegen. Dies ist einfach, wenn Sie Dolch 2 verwenden. Andernfalls erstellen Sie einfach ein Klassenfeld in Ihrer Anwendung.Im
TokenAuthenticator.java
In
TokenServiceHolder.java
:Client-Setup:
Wenn Sie Dagger 2 oder ein ähnliches Framework für die Abhängigkeitsinjektion verwenden, finden Sie in den Antworten auf diese Frage einige Beispiele
quelle
TokenService
Klasse erstellt?refreshToken()
von bereitstellenservice.refreshToken().execute();
. Ich kann die Implementierung nirgendwo finden.Die Verwendung von
TokenAuthenticator
like @ theblang answer ist eine korrekte Methode für den Umgangrefresh_token
.Hier ist mein Gerät (ich habe Kotlin, Dagger, RX verwendet, aber Sie können diese Idee für die Implementierung in Ihrem Fall verwenden).
TokenAuthenticator
Um einen Abhängigkeitszyklus wie @Brais Gabin Kommentar zu verhindern, erstelle ich 2 Schnittstellen wie
und
AccessTokenWrapper
KlasseAccessToken
KlasseMein Abfangjäger
Fügen Sie schließlich
Interceptor
undAuthenticator
zu IhremOKHttpClient
beim Erstellen des Dienstes hinzuFügen Sie PotoAuthApi hinzuDemo
https://github.com/PhanVanLinh/AndroidMVPKotlin
Hinweis
Authenticator FlowgetImage()
401 Fehlercode zurückauthenticate
Methode im InnerenTokenAuthenticator
wird ausgelöstnoneAuthAPI.refreshToken(...)
aufgerufennoneAuthAPI.refreshToken(...)
Antwort -> wird ein neues Token zum Header hinzugefügtgetImage()
wird AUTO mit neuem Header aufgerufen (wird diesen AnrufHttpLogging
NICHT protokollieren ) (intercept
innen wirdAuthInterceptor
NICHT aufgerufen )Wenn
getImage()
immer noch mit Fehler 401, gescheitertauthenticate
Methode innerhalbTokenAuthenticator
Willen feuerte wieder und wieder , dann wird es Fehler über Call - Methode viel Zeit werfen (java.net.ProtocolException: Too many follow-up requests
). Sie können dies verhindern, indem Sie die Antwort zählen . Beispiel : Wenn Siereturn null
inauthenticate
nach 3 - mal wiederholt,getImage()
wird beenden undreturn response 401
Wenn die
getImage()
Antwort erfolgreich ist =>, erhalten wir das Ergebnis normal (wie Sie esgetImage()
ohne Fehler aufrufen ).Hoffe es hilft
quelle
Ich weiß, dass dies ein alter Thread ist, aber nur für den Fall, dass jemand darüber stolpert.
Ich hatte das gleiche Problem, aber ich wollte nur einen OkHttpClient erstellen, da ich nicht glaube, dass ich nur für den TokenAuthenticator selbst einen anderen benötige. Ich habe Dagger2 verwendet, sodass ich die Serviceklasse als Lazy in den TokenAuthenticator, können Sie mehr über faule Injektion in Dolch 2 lesen hier , aber es ist wie im Grunde zu Dagger sagen zu nicht gehen und den Service des TokenAuthenticator sofort benötigt erstellen.
In diesem SO-Thread finden Sie Beispielcode: Wie kann eine zirkuläre Abhängigkeit aufgelöst werden, während Dagger2 noch verwendet wird?
quelle
Sie können versuchen, eine Basisklasse für alle Ihre Loader zu erstellen, in der Sie eine bestimmte Ausnahme abfangen und dann nach Bedarf handeln können. Stellen Sie sicher, dass sich alle Ihre verschiedenen Lader von der Basisklasse aus erstrecken, um das Verhalten zu verbreiten.
quelle
Nach langer Recherche habe ich den Apache-Client so angepasst, dass er das Aktualisieren von AccessToken für die Nachrüstung übernimmt, in dem Sie das Zugriffstoken als Parameter senden.
Initiieren Sie Ihren Adapter mit Cookie Persistent Client
Cookie Persistenter Client, der Cookies für alle Anforderungen verwaltet und bei jeder Anforderungsantwort prüft. Wenn es sich um einen nicht autorisierten Zugriff handelt, ERROR_CODE = 401, aktualisiert das Zugriffstoken und ruft die Anforderung ab, andernfalls verarbeitet er nur die Anforderung.
quelle
Die Verwendung eines Interceptors (Injizieren des Tokens) und eines Authenticators (Aktualisierungsvorgänge) erledigt den Job, aber:
Ich hatte auch ein Problem mit einem doppelten Anruf: Der erste Anruf gab immer einen 401 zurück : Das Token wurde beim ersten Anruf (Interceptor) nicht injiziert und der Authentifikator wurde aufgerufen: Es wurden zwei Anforderungen gestellt.
Das Update bestand nur darin, die Anforderung an den Build im Interceptor erneut zu aktivieren:
VOR:
NACH DEM:
IN EINEM BLOCK:
Ich hoffe es hilft.
Bearbeiten: Ich habe keine Möglichkeit gefunden, den ersten Aufruf zu vermeiden, immer 401 nur mit dem Authentifikator und ohne Interceptor zurückzugeben
quelle
Für alle, die gleichzeitige / parallele Anrufe beim Aktualisieren des Tokens lösen möchten. Hier ist eine Problemumgehung
quelle