Не удается использовать аутентификацию прокси с Https в Java - PullRequest
0 голосов
/ 07 сентября 2018

Описание

Я пытаюсь подключиться к веб-серверу, который использует https, через прокси-сервер, который требует аутентификацию, но он не работает.

Класс HttpsURLConnection отправляет первый запрос на открытие туннеля без заголовка «Proxy-Authorization», даже если принудительно.

В этом случае сервер вернет «407 Proxy Authentication Required».

Код для воспроизведения проблемы

public class TestProxy {

  @Test
  public void testOne() throws IOException {

    final String PROXY_USERNAME = "username";
    final String PROXY_PASSWORD = "password";
    final String PROXY_HOSTNAME = "hostname";
    final int PROXY_PORT = 8080;

    Authenticator.setDefault(
        new Authenticator() {
          @Override
          public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(PROXY_USERNAME, PROXY_PASSWORD.toCharArray());
          }
        });

    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOSTNAME, PROXY_PORT));

    URL url = new URL("https://www.google.com");

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(proxy);

    assertNotEquals(407, connection.getResponseCode());

  }

  @Test
  public void testTwo() throws IOException {

    final String PROXY_USERNAME = "username";
    final String PROXY_PASSWORD = "password";
    final String PROXY_HOSTNAME = "hostname";
    final int PROXY_PORT = 8080;

    Authenticator.setDefault(
        new Authenticator() {
          @Override
          public PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(PROXY_USERNAME, PROXY_PASSWORD.toCharArray());
          }
        });

    Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_HOSTNAME, PROXY_PORT));

    URL url = new URL("https://www.google.com");

    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(proxy);

    String userCredentials = PROXY_USERNAME + ":" + PROXY_PASSWORD;
    String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userCredentials.getBytes()));
    connection.setRequestProperty("Proxy-Authorization", basicAuth);

    assertNotEquals(407, connection.getResponseCode());

  }

}

Запрос отправлен

CONNECT www.google.com:443 HTTP/1.1
User-Agent: Java/1.8.0_162
Host: www.google.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Proxy-Connection: keep-alive

Возможная причина

Я думаю, что это поведение вызвано методом sun.net.www.protocol.http.HttpURLConnection.sendCONNECTRequest() Создает новый «запрос на подключение» без добавления заголовка «Proxy-Authorization».

Обход

Обходное решение - сначала подключиться к http-адресу, чтобы прокси-сервер зарегистрировал пользовательский агент и авторизовал подключение без добавления заголовка Proxy-Authorization

Версия jdk: 1.8.0_181-b13.

1 Ответ

0 голосов
/ 10 сентября 2018

Чтобы иметь возможность подключаться к веб-сервису через https через прокси-сервер, нам нужно отключить системное свойство.

Это требуется только для jdk> 8u11

См Отключить базовую аутентификацию для туннелирования HTTPS

Установка системных свойств в приложении не будет работать

  private void allowAuthenticationForHttps() {
    System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
  }

это должно быть передано как флаг в командной строке

-Djdk.http.auth.tunneling.disabledSchemes=""
...