首页 文章

具有身份验证的Apache HttpClient Socks5代理

提问于
浏览
0

我'm trying to use a Socks5 proxy server for requests to a certain target (host) that requires proxy in my Java application. I'使用Apache Http库(v.4.5.4) . 我有很多不同的其他目标,不需要代理,因此为整个应用程序设置全局代理不是我的选择 . 所以我为 HttpClient 的某个实例设置了代理 . 代理需要使用login和pass进行身份验证 .

我的解决方案基于此question另外添加认证参数,如documentation中所述 .

这是我的代码:

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忽略了提供的凭据并从系统中获取它 .

我究竟做错了什么?

1 回答

  • 0

    我've spent a few days struggling with the same problem. For me, the simplest way is to use java' s 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) 方法 .

    我've tried to use many other methods, but they all don'为我工作 . 我假设 setDefaultCredentialsProvider 正在响应 target 上的身份验证,而不是 proxy . 我没有调试那么深 . 我还在试图弄清楚如何更优雅地解决这个问题 . 如果您能找到更好的解决方案,请与我们联系 .

相关问题