Повторно используйте заголовок авторизации для предотвращения множественных проблем аутентификации прокси 407 с клиентом Jersey.

Я использую библиотеку Jersey Client 2.0 (с транспортным соединителем Apache HttpClient v4.2.5) для использования веб-службы RESTful. Мое приложение должно поддерживать соединения через прокси-сервер с любой базовой, дайджест-проверкой или аутентификацией NTLM. Я добавил поддержку всех этих типов проверки подлинности прокси-сервера и, по сути, все работает правильно.

Вот как я добавил поддержку базовой и дайджест-аутентификации прокси:

ClientConfig config = new ClientConfig();
config.property(ApacheClientProperties.PROXY_URI, "http://www.proxy.com:5678");
config.property(ApacheClientProperties.PROXY_USERNAME, "proxy_user");
config.property(ApacheClientProperties.PROXY_PASSWORD, "proxy_password");
ApacheConnector connector = new ApacheConnector(config);
config.connector(connector);
Client client = ClientBuilder.newClient(config);

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

client.register( new HttpBasicAuthFilter("user", "password") );

Однако мое приложение ведет себя не так, как я хочу: кажется, что каждый отдельный HTTP-запрос, который я делаю, приводит к ответу на запрос аутентификации 407 от прокси-сервера. Это проблема по двум причинам:

  1. Если я сделаю POST или же PUT запрос (уже успешно аутентифицированный прокси-сервером в предыдущем запросе) с телом объекта, предоставленным InputStreamэто считается "неповторяющимся" запросом, поэтому при получении запроса 407 я получаю следующее исключение:

    org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
    

    Я мог бы обойти эту проблему путем буферизации данных тела объекта из InputStream в строку или байтовый массив, чтобы запрос мог повторяться в случае получения запроса 407, но это неэффективно и не решает проблему 2.

  2. Необходимость дублировать каждый запрос, сначала вызвать вызов 407, а затем повторить с необходимыми дополнительными заголовками HTTP для аутентификации прокси, очень неэффективно. Некоторые из моих клиентских операций связаны с многочисленными HTTP-запросами к веб-сервису RESTful, поэтому этот дополнительный трафик и задержка неутешительны.

Я ожидаю, что как только клиент Джерси успешно пройдет аутентификацию на прокси-сервере в первый раз, все последующие запросы будут выполнены с использованием того же Client Экземпляр будет автоматически включать необходимые Proxy-Authorization заголовок, чтобы предотвратить любые дальнейшие 407 проблем. Похоже, что это стандартный подход для HTTP 1.1 по этой ссылке:

Прокси-сервер отправляет клиенту заголовок Proxy-Authenticate, содержащий запрос, в ответе 407 (Proxy Authentication Required). Затем клиент повторяет первоначальный запрос, но добавляет заголовок Proxy-Authorization, содержащий учетные данные, соответствующие запросу. После успешной аутентификации прокси-клиента клиент обычно отправляет один и тот же заголовок Proxy-Authorization на прокси-сервер с каждым последующим запросом, вместо того чтобы ждать повторного вызова.

Поэтому мой вопрос: какие параметры конфигурации мне нужно применить к клиенту Jersey или к базовому транспортному уровню Apache HttpClient, чтобы включить это поведение? Я видел различные другие посты, рекомендующие ручное добавление Proxy-Authorization заголовок, но я бы предпочел избежать этого обходного пути, если это возможно. Я также в идеале ищу решение, которое будет работать со всеми тремя типами прокси-аутентификации, которые я использую (Basic, Digest и NTLM).

Если невозможно предотвратить все эти дополнительные проблемы 407, я также хотел бы получить рекомендации по наилучшему подходу при размещении или извлечении данных из локальных файлов "повторяемым" способом, чтобы предотвратить проблемы после проверки подлинности прокси-сервера 407.

1 ответ

Решение

В конце концов, я решил проблему 1, обновив свой проект до версии Jersey Client v2.6 и настроив клиент для автоматической буферизации всех моих запросов POST/PUT так, чтобы они были "повторяемыми" в ответ на любые 407 вызовов, возвращаемых прокси-сервером. сервер.

Буферизацию запросов можно включить в Jersey Client v2.5+, установив следующее свойство на ClientConfig объект, который изменяет режим обработки объекта запроса с "chunked" (по умолчанию) на "buffered":

config.property(ClientProperties.REQUEST_ENTITY_PROCESSING,
                RequestEntityProcessing.BUFFERED);

Теперь это работает для меня со всеми тремя типами аутентификации прокси, которые я должен поддерживать: Basic, Digest и NTLM. Я включаю этот "буферизованный" режим только тогда, когда пользователь настроил прокси-сервер, так как я думаю, что лучше придерживаться стандартного "чанкированного" режима, если в этом нет крайней необходимости. Я беспокоюсь о накладных расходах на буферизацию больших запросов PUT/POST в памяти и о потенциальной потере эффективности из-за отсутствия разбивки данных.

Итак, теперь мое клиентское приложение работает должным образом, но мне все равно было бы очень интересно узнать о любых возможных решениях для проблемы 2, так как было бы предпочтительнее инициировать только одну первоначальную проверку подлинности прокси-сервера 407 в Client пример. Я подозреваю, что любое потенциальное решение этой проблемы в любом случае будет работать только для базовой аутентификации из-за дополнительных сложностей, связанных с дайджестом и аутентификацией NTLM.

Другие вопросы по тегам