Прокси-сервер Apache HttpClient Socks5 с аутентификацией

Я пытаюсь использовать прокси-сервер Socks5 для запросов к определенной цели (хосту), для которой требуется прокси в моем приложении Java. Я использую библиотеку Apache Http (v. 4.5.4). У меня есть много других целей, которым не требуется прокси, поэтому глобальная настройка прокси для всего приложения для меня не вариант. Итак, я установил прокси для определенного экземпляра HttpClient. Прокси требует аутентификации с логином и паролем.

Мое решение основано на этом вопрос, дополнительно добавив параметры аутентификации, как описано в документации< /а>.

Вот мой код:

private void sendSocks5Request(StringEntity requestEntity) throws Exception {

        Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new MyConnectionSocketFactory(SSLContexts.createSystemDefault()))
                .build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg);

        Credentials credentials = new UsernamePasswordCredentials("proxy_user","proxy_pass");
        AuthScope authScope = new AuthScope("my.proxy.com", 1080);
        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(authScope, credentials);

        CloseableHttpClient httpclient = HttpClients.custom()
                .setConnectionManager(cm)
                .setDefaultCredentialsProvider(credsProvider)
                .build();

        try {
            InetSocketAddress socksaddr = new InetSocketAddress("my.proxy.com", 1080);
            HttpClientContext context = HttpClientContext.create();
            context.setAttribute("socks.address", socksaddr);

            HttpHost target = new HttpHost("api.telegram.org", 80, "https");
            HttpPost request = new HttpPost("/bot<bot_token_here>");
            request.setEntity(requestEntity);

            System.out.println("Executing request " + request + " to " + target + " via SOCKS proxy " + socksaddr);
            CloseableHttpResponse response = httpclient.execute(target, request, context);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                EntityUtils.consume(response.getEntity());
            } catch (Exception ex) {
                ex.getMessage();
            } finally {
                response.close();
            }
        } catch (Exception ex) {
            ex.getMessage();
        } finally {
            httpclient.close();
        }
}

Прокси вроде работает, но получаю ошибку Authentication failed. Журналы на самом прокси-сервере показывают, что предоставленная аутентификация содержит не пользователя proxy_user, а системного пользователя моей машины. Таким образом, похоже, что HttpClient игнорирует предоставленные учетные данные и берет их из системы.

Что я делаю неправильно?


person Emptyfruit    schedule 10.07.2018    source источник
comment
У нас та же проблема, прокси-сервер, который мы используем, не требует аутентификации, но поскольку наш java-код по существу отправляет системного пользователя (что на самом деле является проблемой безопасности, поскольку он предлагает информацию, которая не нужна целевой системе !!!) прокси-сервер бросает ошибка, которая приводит к сбою всей связи. Вы каким-то образом проделали путь? Кажется, этот вопрос - единственный, который решает эту проблему!   -  person DJGummikuh    schedule 09.11.2018


Ответы (1)


Я провел несколько дней, борясь с той же проблемой. Для меня самый простой способ - использовать Java Authenticator Просто добавьте этот код перед execute:

Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(proxyUser, proxyPassword.toCharArray());
    }
});

После этого сокет должен отправить ваши учетные данные. Вы можете отладить метод java.net.SocksSocketImpl#authenticate(byte, java.io.InputStream, java.io.BufferedOutputStream, long), если у вас есть интерес.

Я пытался использовать много других методов, но все они не работают для меня. Я предполагаю, что setDefaultCredentialsProvider отвечает за аутентификацию на target, а не на proxy. Я еще не отлаживал так глубоко. Я все еще пытаюсь понять, как решить эту проблему более элегантно. Дайте мне знать, если вы найдете лучшее решение.

person I V    schedule 14.11.2018