Упреждающая аутентификация прокси-сервера с HTTP-туннелем / HTTPS-соединением в Apache HttpClient 4.3.1

Я пытаюсь отправить HTTPS-запрос через прокси-сервер, которому требуется упреждающая аутентификация с использованием Apache HttpClient 4.3.1.

Мой прокси-сервер блокирует соединения с моего IP-адреса на несколько минут, когда я не аутентифицирую себя напрямую в первом запросе.

У меня не было проблем с обычными HTTP-запросами, я просто вручную добавил в запрос заголовок «Proxy-Authorization».

Но при попытке загрузить страницу HTTPS HttpClient, похоже, использует HTTP-туннель, поэтому первым запросом является команда «CONNECT», после чего отправляется мой фактический запрос. Использование метода request.setHeader(...) не влияет на заголовки запроса CONNECT, что приводит к ответу «HTTP/1.0 407 Proxy Authentication Required» и закрытию моего соединения. После этого HttpClient снова подключается, на этот раз добавляя поле заголовка «Proxy-Authorization» с моими учетными данными.

Соединение установлено успешно (соединение HTTP/1.0 200 установлено), и мой фактический запрос GET выполняется. НО, когда я снова запущу свою программу после этого, я получу IOException:

Информация: исключение ввода-вывода (java.net.SocketException), обнаруженное при обработке запроса: сброс соединения

В Wireshark я вижу, что прокси-сервер больше не отвечает на мои запросы «CONNECT» (которые не содержат учетных данных). Поэтому я попробовал несколько способов заставить HttpClient отправлять учетные данные в первом запросе CONNECT: я адаптировал этот example для использования прокси и создал AuthCache для прокси, но это не сработало. Я также попытался добавить HttpRequestInterceptor к моему клиенту:

static class PreemptiveAuth implements HttpRequestInterceptor {
    @Override
    public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
        request.setHeader("Proxy-Authorization", "Basic <base64credentials>");
    }
}

Но это также не влияет на запросы «CONNECT». Вот остальная часть моего кода:

public class ClientProxyAuthentication {

public static void main(String[] args) throws IOException, InterruptedException {
    HttpHost targetHost = new HttpHost("www.google.com", 443, "https");
    HttpHost proxy = new HttpHost("<proxy-ip>", 21265, "http");

    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(
            new AuthScope("<proxy-ip>", 21265),
            new UsernamePasswordCredentials("username", "pass"));

    CloseableHttpClient httpclient = HttpClients.custom()
            .addInterceptorFirst(new PreemptiveAuth())
            .setProxy(proxy)
            .setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy())
            .setDefaultCredentialsProvider(credsProvider).build();


    try {

        HttpGet httpget = new HttpGet("/");
        httpget.setHeader("Proxy-Authorization", "Basic <base64credentials>");

        System.out.println("executing request: " + httpget.getRequestLine());
        System.out.println("via proxy: " + proxy);
        System.out.println("to target: " + targetHost);

        CloseableHttpResponse response = httpclient.execute(targetHost, httpget);
        try {
            HttpEntity entity = response.getEntity();

            System.out.println("----------------------------------------");
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
            }
            String html = EntityUtils.toString(entity, "UTF-8");
            System.out.println(html);
            EntityUtils.consume(entity);
        } finally {
            response.close();
        }
    } finally {
        httpclient.close();
    }
}

person user3194986    schedule 14.01.2014    source источник


Ответы (1)


Я подозреваю, что вы неправильно инициализировали кеш авторизации. Пожалуйста, попробуйте это.

HttpHost proxy = new HttpHost("proxy", 8080);

BasicScheme proxyAuth = new BasicScheme();
// Make client believe the challenge came form a proxy
proxyAuth.processChallenge(new BasicHeader(AUTH.PROXY_AUTH, "BASIC realm=default"));
BasicAuthCache authCache = new BasicAuthCache();
authCache.put(proxy, proxyAuth);

CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        new AuthScope(proxy),
        new UsernamePasswordCredentials("username", "password"));

HttpClientContext context = HttpClientContext.create();
context.setAuthCache(authCache);
context.setCredentialsProvider(credsProvider);

CloseableHttpClient httpclient = HttpClients.createDefault();
try {
    CloseableHttpResponse response = httpclient.execute(new HttpGet("/stuff"), context);
    try {
        // ...
    } finally {
        response.close();
    }
} finally {
    httpclient.close();
}
person ok2c    schedule 16.01.2014