Android OkHttp avec authentification de base

J’utilise la bibliothèque OkHttp pour un nouveau projet et je suis impressionné par sa facilité d’utilisation. J’ai maintenant besoin d’utiliser l’authentification de base. Malheureusement, il y a une pénurie de code exemple de travail. Je cherche un exemple de la façon de transmettre les informations d’identification de nom d’utilisateur / mot de passe à OkAuthenticator lorsqu’un en-tête HTTP 401 est rencontré. J’ai vu cette réponse:

Demande de mise à jour POST avec authentification HTTP de base: “Impossible de réessayer le corps HTTP en streaming”

mais ça ne m’a pas trop poussé. Les exemples sur le repository github OkHttp ne comportaient pas non plus d’échantillon basé sur l’authentification. Est-ce que quelqu’un a un aperçu ou un autre exemple de code pour me diriger dans la bonne direction? Merci pour votre aide!

Essayez d’utiliser OkAuthenticator :

client.setAuthenticator(new OkAuthenticator() { @Override public Credential authenticate( Proxy proxy, URL url, List challenges) throws IOException { return Credential.basic("scott", "tiger"); } @Override public Credential authenticateProxy( Proxy proxy, URL url, List challenges) throws IOException { return null; } }); 

METTRE À JOUR:

Renommé en authentificateur

Code de mise à jour pour okhttp3:

 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!! } Ssortingng 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; } } 

Voici le code mis à jour:

 client.setAuthenticator(new Authenticator() { @Override public Request authenticate(Proxy proxy, Response response) throws IOException { Ssortingng 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; } }) 

Comme l’a souligné @agamov:

La solution susmentionnée présente un inconvénient: httpClient ajoute des en-têtes d’autorisation uniquement après avoir reçu une réponse 401

@agamov a alors proposé d’append “manuellement” des en-têtes d’authentification à chaque requête, mais il existe une meilleure solution: utiliser un Interceptor :

 import java.io.IOException; import okhttp3.Credentials; import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response; public class BasicAuthInterceptor implements Interceptor { private Ssortingng credentials; public BasicAuthInterceptor(Ssortingng user, Ssortingng 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); } } 

Ensuite, ajoutez simplement l’intercepteur à un client OkHttp que vous utiliserez pour effectuer toutes vos requêtes authentifiées:

 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new BasicAuthInterceptor(username, password)) .build(); 

La solution susmentionnée présente un inconvénient: httpClient ajoute des en-têtes d’autorisation uniquement après avoir reçu une réponse 401. Voici à quoi ressemblait ma communication avec api-server: entrer la description de l'image ici

Si vous devez utiliser basic-auth pour chaque requête, mieux vaut append vos en-têtes d’authentification à chaque requête ou utiliser une méthode d’encapsulation comme celle-ci:

 private Request addBasicAuthHeaders(Request request) { final Ssortingng login = "your_login"; final Ssortingng password = "p@s$w0rd"; Ssortingng credential = Credentials.basic(login, password); return request.newBuilder().header("Authorization", credential).build(); } 

Okhttp3 avec base 64 auth

 Ssortingng endpoint = "https://www.example.com/m/auth/" Ssortingng username = "user123"; Ssortingng password = "12345"; Ssortingng credentials = username + ":" + password; final Ssortingng basic = "Basic " + Base64.encodeToSsortingng(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() { ... 

Toutes les réponses sont bonnes mais personne n’a dit que pour certaines requêtes , le type de contenu est requirejs, vous devez append un type de contenu à votre requête comme ceci:

 Request request = new Request.Builder() .url(url) .addHeader("content-type", "application/json") .post(body) .build(); 

Si vous ne l’ajoutez pas, vous obtiendrez un message non autorisé et vous perdrez beaucoup de temps à le réparer.

Quelqu’un a demandé une version Kotlin de l’intercepteur. Voici ce que j’ai trouvé et ça marche super bien:

  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() 

J’ai remarqué sur Android avec certaines API de serveur comme Django que vous devriez append un mot en jeton

 Request request = new Request.Builder() .url(theUrl) .header("Authorization", "Token 6utt8gglitylhylhlfkghriyiuy4fv76876d68") .build(); 

, où ce mot problématique est ce “Token”. Dans l’ensemble, vous devriez voir attentivement les règles de ces API de serveur spécifiques sur la façon de composer les requêtes.