Ich verwende die OkHttp-Bibliothek für ein neues Projekt und bin beeindruckt von der Benutzerfreundlichkeit. Ich muss jetzt die Standardauthentifizierung verwenden. Leider mangelt es an funktionierendem Beispielcode. Ich suche ein Beispiel für die Übergabe von Benutzernamen- / Kennwortanmeldeinformationen an den OkAuthenticator, wenn ein HTTP 401-Header gefunden wird. Ich habe diese Antwort angesehen:
aber es hat mich nicht zu weit gebracht. Die Samples auf dem OkHttp Github Repo enthielten auch kein authentifizierungsbasiertes Sample. Hat jemand einen Kern oder ein anderes Codebeispiel, um mich in die richtige Richtung zu lenken? Danke für deine Hilfe!
Antworten:
Versuchen Sie es mit OkAuthenticator :
client.setAuthenticator(new OkAuthenticator() { @Override public Credential authenticate( Proxy proxy, URL url, List<Challenge> challenges) throws IOException { return Credential.basic("scott", "tiger"); } @Override public Credential authenticateProxy( Proxy proxy, URL url, List<Challenge> challenges) throws IOException { return null; } });
AKTUALISIEREN:
In Authenticator umbenannt
quelle
Code für okhttp3 aktualisieren:
import okhttp3.Authenticator; import okhttp3.Credentials; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.Route; public class NetworkUtil { private final OkHttpClient.Builder client; { client = new OkHttpClient.Builder(); client.authenticator(new Authenticator() { @Override public Request authenticate(Route route, Response response) throws IOException { if (responseCount(response) >= 3) { return null; // If we've failed 3 times, give up. - in real life, never give up!! } String credential = Credentials.basic("name", "password"); return response.request().newBuilder().header("Authorization", credential).build(); } }); client.connectTimeout(10, TimeUnit.SECONDS); client.writeTimeout(10, TimeUnit.SECONDS); client.readTimeout(30, TimeUnit.SECONDS); } private int responseCount(Response response) { int result = 1; while ((response = response.priorResponse()) != null) { result++; } return result; } }
quelle
never give up
Kommentar XDWie von @agamov hervorgehoben:
@agamov schlug dann vor, jeder Anforderung "manuell" Authentifizierungsheader hinzuzufügen, aber es gibt eine bessere Lösung: Verwenden Sie eine
Interceptor
:import java.io.IOException; import okhttp3.Credentials; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class BasicAuthInterceptor implements Interceptor { private String credentials; public BasicAuthInterceptor(String user, String password) { this.credentials = Credentials.basic(user, password); } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request authenticatedRequest = request.newBuilder() .header("Authorization", credentials).build(); return chain.proceed(authenticatedRequest); } }
Fügen Sie dann einfach den Interceptor zu einem OkHttp-Client hinzu, mit dem Sie alle Ihre authentifizierten Anforderungen stellen:
OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new BasicAuthInterceptor(username, password)) .build();
quelle
Hier ist der aktualisierte Code:
client.setAuthenticator(new Authenticator() { @Override public Request authenticate(Proxy proxy, Response response) throws IOException { String credential = Credentials.basic("scott", "tiger"); return response.request().newBuilder().header("Authorization", credential).build(); } @Override public Request authenticateProxy(Proxy proxy, Response response) throws IOException { return null; } })
quelle
Die oben genannte Lösung hat einen Nachteil: httpClient fügt Autorisierungsheader erst nach Erhalt der 401-Antwort hinzu. So sah meine Kommunikation mit dem API-Server aus:
Wenn Sie Basic-Auth für jede Anforderung verwenden müssen, fügen Sie Ihre Auth-Header besser zu jeder Anforderung hinzu oder verwenden Sie eine Wrapper-Methode wie die folgende:
private Request addBasicAuthHeaders(Request request) { final String login = "your_login"; final String password = "p@s$w0rd"; String credential = Credentials.basic(login, password); return request.newBuilder().header("Authorization", credential).build(); }
quelle
Okhttp3 mit Base 64 Auth
String endpoint = "https://www.example.com/m/auth/" String username = "user123"; String password = "12345"; String credentials = username + ":" + password; final String basic = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); Request request = new Request.Builder() .url(endpoint) .header("Authorization", basic) .build(); OkHttpClient client = SomeUtilFactoryClass.buildOkhttpClient(); client.newCall(request).enqueue(new Callback() { ...
quelle
okhttp3.Credentials.basic(user, pass)
tut dies, also denke ich, dass es bevorzugt werden sollte (nur weil es zu weniger Code führt, um es zu erhalten).okhttp3.Credentials.basic(user, pass)
stellt keine Anforderungen oder ändert kein Verhalten, sondern konvertiert einfach den Benutzernamen und das Kennwort in eine grundlegende Authentifizierungszeichenfolge.Jemand fragte nach einer Kotlin-Version des Abfangjägers. Folgendes habe ich mir ausgedacht und es funktioniert großartig:
val client = OkHttpClient().newBuilder().addInterceptor { chain -> val originalRequest = chain.request() val builder = originalRequest.newBuilder() .header("Authorization", Credentials.basic("ausername", "apassword")) val newRequest = builder.build() chain.proceed(newRequest) }.build()
quelle
In meinem Fall hat es nur funktioniert, wenn ich die Autorisierung in den Header integriert habe (OkHttp Version 4.0.1):
Request request = new Request.Builder() .url("www.url.com/api") .addHeader("Authorization", Credentials.basic("username", "password")) .build(); Request response = client.newCall(request).execute();
quelle
Ich habe auf Android mit einigen Server-APIs wie Django bemerkt, dass Sie ein Wort in Token hinzufügen sollten
Request request = new Request.Builder() .url(theUrl) .header("Authorization", "Token 6utt8gglitylhylhlfkghriyiuy4fv76876d68") .build();
, wo dieses problematische Wort das "Token" ist. Insgesamt sollten Sie die Regeln dieser spezifischen Server-APIs zum Erstellen von Anforderungen sorgfältig lesen.
quelle
Bearer 6utt8gglitylhylhlfkghriyiuy4fv76876d68
In OkHttp3 legen Sie die Berechtigung für sich
OkHttpClient
selbst fest, indem Sie dieauthenticator()
Methode hinzufügen . Nachdem Ihr ursprünglicher Anruf mit der Antwort 401 zurückkommt, wirdthe authenticator()
derAuthorization
Header hinzugefügtnew OkHttpClient.Builder() .connectTimeout(10000, TimeUnit.MILLISECONDS) .readTimeout(10000, TimeUnit.MILLISECONDS) .authenticator(new Authenticator() { @Nullable @Override public Request authenticate(@NonNull Route route, @NonNull Response response) { if (response.request().header(HttpHeaders.AUTHORIZATION) != null) return null; //if you've tried to authorize and failed, give up String credential = Credentials.basic("username", "pass"); return response.request().newBuilder().header(HttpHeaders.AUTHORIZATION, credential).build(); } }) .build();
Obwohl es sicherer ist, können Sie, wenn Sie den Server überhaupt nicht mit allen 401-Anforderungen als Spam versenden möchten, eine sogenannte Vorauthentifizierung verwenden, bei der Sie den
Authorization
Header zunächst für Ihre Anforderungen sendenString credentials = Credentials.basic("username", "password"); Request httpRequest = new Request.Builder() .url("some/url") .header("content-type", "application/json") .header(HttpHeaders.AUTHORIZATION, credentials) .build();
quelle
Alle Antworten sind gut, aber niemand sagte, dass für einige Anfragen der Inhaltstyp erforderlich ist. Fügen Sie Ihrer Anfrage einen Inhaltstyp wie folgt hinzu:
Request request = new Request.Builder() .url(url) .addHeader("content-type", "application/json") .post(body) .build();
Wenn Sie es nicht hinzufügen, erhalten Sie eine nicht autorisierte Nachricht und verschwenden viel Zeit, um es zu beheben.
quelle
Dies ist ein Ausschnitt für OkHttp Client:
OkHttpClient client = new OkHttpClient.Builder() .authenticator(new Authenticator() { @Override public Request authenticate(Route route, Response response) throws IOException { if (response.request().header("Authorization") != null) { return null; // Give up, we've already attempted to authenticate. } System.out.println("Authenticating for response: " + response); System.out.println("Challenges: " + response.challenges()); String credential = Credentials.basic(username, password); return response.request().newBuilder() .header("Authorization", credential) .build(); } }) .build();
Machen Sie jetzt eine Anfrage. Die Basisauthentifizierung wird ausgeführt, da der Client dies bereits hat.
Request request = new Request.Builder().url(JIRAURI+"/issue/"+key).build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { System.out.println("onFailure: "+e.toString()); } @Override public void onResponse(Call call, Response response) throws IOException { System.out.println( "onResponse: "+response.body().string()); } });
quelle