【问题标题】:Cannot use Proxy Authentification with Https in Java无法在 Java 中将代理身份验证与 Https 一起使用
【发布时间】:2018-09-07 13:49:24
【问题描述】:

说明

我正在尝试通过需要身份验证的代理连接到使用 https 的 Web 服务器,但它不起作用。

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()引起的 它创建一个新的“连接请求”而不添加“代理授权”标头。

解决方法

解决方法是首先连接到一个 http 地址,这样代理服务器将注册用户代理并授权连接而不添加 Proxy-Authorization 标头

jdk版本为1.8.0_181-b13。

【问题讨论】:

    标签: java https proxy httpurlconnection


    【解决方案1】:

    为了能够通过代理使用 https 连接到 web 服务,我们需要禁用系统属性。

    这仅对 jdk > 8u11

    是必需的

    Disable Basic authentication for HTTPS tunneling

    在应用程序中设置系统属性将不起作用

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

    它应该在命令行中作为标志传递

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-19
      • 1970-01-01
      • 2018-12-21
      • 2023-03-25
      • 2014-08-05
      相关资源
      最近更新 更多