Заголовок авторизации аутентификации HttpClient Digest в Android жестко запрограммирован

Мы пытаемся отправить несколько запросов на целевой сервер за один HttpClient (один сеанс). Целевой сервер сначала аутентифицирует все запросы с помощью дайджест-аутентификации (на основе MD5-sessions). Результат показывает, что только первый доступ является успешным. Следующие ниже обращения отклоняются сервером, поскольку сервер рассматривает последующие обращения как атаку повторного воспроизведения, поскольку значение «nc» всегда равно «00000001».

Кажется, что Android HttpClient жестко запрограммировал заголовок авторизации дайджеста attirbute "nc" на "00000001"?

Есть ли способ для клиента увеличить это значение при отправке нового запроса? Спасибо.

public class HttpService {

private static final HttpService instance = new HttpService();
private HttpService() {
    client = getHttpClient();
}

public static HttpService getInstance() {
    return instance;
}

private DefaultHttpClient getHttpClient() {
    HttpParams params = new BasicHttpParams();
    HttpConnectionParams.setStaleCheckingEnabled(params, false);
    HttpConnectionParams.setConnectionTimeout(params, 15 * 1000);
    HttpConnectionParams.setSoTimeout(params, 15 * 1000);
    HttpConnectionParams.setSocketBufferSize(params, 8192);
    HttpProtocolParams.setUserAgent(params, USER_AGENT);

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    Scheme httpScheme = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
    Scheme httpsScheme = new Scheme("https", SSLCertificateSocketFactory.getHttpSocketFactory(30 * 1000, null), 443);
    schemeRegistry.register(httpScheme);
    schemeRegistry.register(httpsScheme);
    ClientConnectionManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);

    //create client
    DefaultHttpClient httpClient = new DefaultHttpClient(manager, params);

    httpClient.getCredentialsProvider().setCredentials(new AuthScope(address, port),
                new UsernamePasswordCredentials(username, password));
}

}


person lyobwon    schedule 23.03.2012    source источник
comment
Как вы инициализируете свой HttpClient? Разместите код.   -  person Nikolay Elenkov    schedule 23.03.2012
comment
Инициализация очень распространена. Я добавляю пример кода в исходный пост. Спасибо   -  person lyobwon    schedule 23.03.2012


Ответы (2)


Android поставляется с сильно устаревшей (до бета-версии) вилкой Apache HttpClient. Начиная с 4.0 ALPHA, в стандартную версию HttpClient было внесено бесчисленное количество изменений, также в области аутентификации Digest.

Лучшее, что вы можете сделать, - это скопировать DigestScheme из стандартной версии Apache HttpClient и настроить приложение на использование копии вместо реализации по умолчанию.

https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/DigestScheme.java < / а>

Для этого вам нужно будет зарегистрировать собственный экземпляр DigestSchemeFactory в реестре схем аутентификации.

https://github.com/apache/httpcomponents-client/blob/master/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/DigestSchemeFactory.java < / а>

person ok2c    schedule 23.03.2012

Кажется, ты прав. Это от Digest.java:

//TODO: supply a real nonce-count, currently a server will interprete a repeated request as a replay
private static final String NC = "00000001"; //nonce-count is always 1

Вы должны сообщить об ошибке на http://b.android.com. У вас есть несколько вариантов:

  • рассчитать дайджест и самостоятельно создать заголовок, а затем установить его при каждом запросе. Вы можете добавить HttpRequestInterceptor, чтобы сделать это автоматическим (не устанавливайте учетные данные для поставщика учетных данных)
  • Схемы аутентификации AFAIK должны быть подключаемыми, поэтому правильно реализуйте дайджест-аутентификацию и настройте своего клиента для его использования.
  • использовать другую клиентскую библиотеку HTTP.

РЕДАКТИРОВАТЬ: поскольку он исправлен в стандартной версии, есть еще одна альтернатива:

Другая альтернатива:

  • измените имя пакета Apache HttpClient с помощью jarjar, упакуйте его вместе с приложением и вообще не используйте систему Android.
person Nikolay Elenkov    schedule 23.03.2012