账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    HttpsURLConnection通过代理访问如何设置Proxy-Authorization
    42
    0

    在代码里已经设置了conn.setRequestProperty("Proxy-Authorization", auth);但这个设置只对正式的请求有效,通过wireshark发现在发出正式请求前,会先发出一个CONNECT请求来建立Tunnel,而这个CONNECT请求是没有设置Proxy-Authorization请求头的,导致应答返回407.通过分析源码找到如下代码段:

    private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOException {
        AuthenticationInfo pauth
            = AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
                                              http.getProxyPortUsed());
        if (pauth != null && pauth.supportsPreemptiveAuthorization()) {
            String value;
            if (pauth instanceof DigestAuthentication) {
                DigestAuthentication digestProxy = (DigestAuthentication) pauth;
                if (tunnelState() == TunnelState.SETUP) {
                    value = digestProxy
                        .getHeaderValue(connectRequestURI(url), HTTP_CONNECT);
                } else {
                    value = digestProxy.getHeaderValue(getRequestURI(), method);
                }
            } else {
                value = pauth.getHeaderValue(url, method);
            }
    
            // Sets "Proxy-authorization"
            requests.set(pauth.getHeaderName(), value);
            currentProxyCredentials = pauth;
        }
    }
    

    会有一个缓存来根据proxyHost和proxyPort来缓存其验证信息,但不知道这个验证信息该如何正确设置。继续分析源码,再第一次请求失败后会判断是否为407,如果是的话会通过Authenticator获取用户名密码信息并缓存,这样似乎可以通过

        Authenticator authenticator = new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return (new PasswordAuthentication("admin", "Admin@2018!".toCharArray()));
            }
        };
        Authenticator.setDefault(authenticator);

    来设置用户名和密码,发送第一次的时候回返回407,然后根据应答和Authenticator创建并缓存验证信息,那么第二次应该会成功,但是如下的测试代码两次全都失败了

    public static void main(String[] a) {
    
        Authenticator authenticator = new Authenticator() {
    
            public PasswordAuthentication getPasswordAuthentication() {
                return (new PasswordAuthentication("admin", "admin".toCharArray()));
            }
        };
        Authenticator.setDefault(authenticator);
        
        try {
            testSend();
        } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
        }
        try {
            testSend();
        } catch (KeyManagementException | NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
        }
    }
    
    private static void testSend() throws KeyManagementException, NoSuchAlgorithmException, IOException {
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, new TrustManager[] { new DisabledValidationTrustManager() }, null);
        SSLSocketFactory sslFactory = sslContext.getSocketFactory();
    
        Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress("host", port));
        String auth = "Basic " + Base64.getEncoder().encodeToString("admin:admin".getBytes());
    
        URL url = new URL("https://www.baidu.com");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(proxy);
        conn.setRequestProperty("Proxy-Authorization", auth);
        conn.setDoInput(true);
        conn.setHostnameVerifier((v1, v2) -> true);
        conn.setSSLSocketFactory(sslFactory);
        conn.setRequestMethod("GET");
        conn.connect();
        System.out.println(conn.getResponseCode());
        System.out.println(conn.getResponseMessage());
        conn.disconnect();
    }
    

    因为这写代码并没有开源,所以无法debug,以上只能通过观察分析,在网上找了半天使用方法也没有找到,不知道有没有人知道这个要怎么使用?

    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 捉鳖 普通会员 1楼

      在使用HTTPSURLConnection通过代理访问时,你可以通过以下步骤设置Proxy-Authorization:

      1. 首先,你需要获取到你的代理服务器的URL。这通常可以在你的代理服务器的设置中找到。

      2. 然后,你需要将你的代理服务器的URL添加到HTTPSURLConnection的代理列表中。这可以通过设置setProxyHost方法来实现。

      java URL url = new URL("http://proxy.example.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("Proxy-Host", "proxy.example.com"); connection.setRequestProperty("Proxy-User-Agent", "Mozilla/5.0"); connection.setRequestProperty("Proxy-Port", "8080");

      注意,你需要将"proxy.example.com"替换为你的代理服务器的URL。

      1. 如果你希望HTTP请求自动转换为HTTPS请求,你可以设置setDoOutput方法为true

      java connection.setRequestProperty("Proxy-Do-Output", "true");

      1. 最后,你需要创建一个HTTPSURLConnection对象并使用它来访问服务器。

      java URL url = new URL("https://example.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("User-Agent", "Mozilla/5.0"); connection.setRequestProperty("Accept-Encoding", "gzip, deflate"); connection.setRequestProperty("Proxy-Authorization", "Basic " + Base64.getEncoder().encodeToString(((Proxyunnel) proxy).getCredentials()));

      在这个例子中,我们使用了一个名为Proxyunnel的代理类来设置代理。这个类的构造函数接受一个代理服务器的URL和一个用户的密码。

      注意:这个例子假设你已经在你的代理服务器上设置了一个名为"Proxy-Authorization"的字段,其中包含一个包含用户名和密码的字符串。你需要将"Basic " + Base64.getEncoder().encodeToString(((Proxyunnel) proxy).getCredentials()))替换为你的代理服务器的实际值。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部