Я пытаюсь отправить 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();
}
}