簡體   English   中英

具有身份驗證的Apache HttpClient Socks5代理

[英]Apache HttpClient Socks5 proxy with authentication

我正在嘗試使用Socks5代理服務器來請求對某個目標(主機)的請求,該目標需要Java應用程序中的代理。 我正在使用Apache Http庫(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會忽略提供的憑據,並從系統中獲取它。

我究竟做錯了什么?

我花了幾天的時間來解決同樣的問題。 對我來說,最簡單的方法是使用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)可以調試java.net.SocksSocketImpl#authenticate(byte, java.io.InputStream, java.io.BufferedOutputStream, long)方法。

我嘗試使用許多其他方法,但是它們都不對我有用。 我假設setDefaultCredentialsProvider正在對target而不是對proxy進行身份驗證。 我還沒有調試那么深。 我仍然試圖找出如何更優雅地解決此問題的方法。 讓我知道您是否會找到更好的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM