Подтвердить что ты не робот

Android OkHttp с базовой аутентификацией

Я использую библиотеку OkHttp для нового проекта, и я впечатлен ее простотой использования. Теперь мне нужно использовать базовую аутентификацию. К сожалению, существует недостаток рабочего образца кода. Я ищу пример того, как передавать учетные данные имени пользователя и пароля в OkAuthenticator, когда встречается заголовок HTTP 401. Я просмотрел этот ответ:

Повторная установка запроса POST с базовой аутентификацией HTTP: "Невозможно повторить поток техаз HTTP-тега"

но это не заставило меня зайти слишком далеко. Образцы на OkHttp github repo также не содержали образец, основанный на проверке подлинности. Кто-нибудь имеет сущность или другой образец кода, чтобы заставить меня указать в правильном направлении? Спасибо за вашу помощь!

4b9b3361

Ответ 1

Попробуйте использовать 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;
  }
});

UPDATE:

Переименовано в Authenticator

Ответ 2

Здесь обновленный код:

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;
  }
})

Ответ 3

Обновить код для 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!!
            }
            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;
}

}

Ответ 4

Как указано @agamov:

У вышеупомянутого решения есть один недостаток: httpClient добавляет заголовки авторизации только после получения ответа 401

@agamov предложил затем "вручную" добавить заголовки аутентификации к каждому запросу, но есть лучшее решение: используйте 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);
    }

}

Затем просто добавьте перехватчик к клиенту OkHttp, который вы будете использовать, чтобы выполнить все ваши аутентифицированные запросы:

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

Ответ 5

У вышеупомянутого решения есть один недостаток: httpClient добавляет заголовки авторизации только после получения ответа 401. Вот как мое общение с api-сервером выглядело так: введите описание изображения здесь

Если вам нужно использовать basic-auth для каждого запроса, лучше добавьте свои заголовки auth для каждого запроса или используйте метод обертки, подобный этому:

private Request addBasicAuthHeaders(Request request) {
    final String login = "your_login";
    final String password = "[email protected]$w0rd";
    String credential = Credentials.basic(login, password);
    return request.newBuilder().header("Authorization", credential).build();
}

Ответ 6

Okhttp3 с базой 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() {
...

Ответ 7

Все ответы хороши, но никто не сказал, что для некоторых запросов требуется тип содержимого, вы должны добавить тип контента в свой запрос следующим образом:

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

Если вы не добавите его, вы получите сообщение Unauthorized, и вы потратите много времени, чтобы исправить его.

Ответ 8

Я заметил на Android с некоторыми API-интерфейсами серверов, например, django, вы должны добавить слово в токен

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

где это проблематичное слово - это "токен". В целом вы должны внимательно ознакомиться с правилами этих API-интерфейсов сервера о том, как составлять запросы.