关于 java:使用 JDK 11 HttpClient 进行代理身份验证

Proxy Authentication with JDK 11 HttpClient

我正在尝试使用 JDK 11 HttpClient 通过公司代理发出请求,该代理需要通过登录名和密码进行身份验证。根据 JDK 的介绍,我正在通过以下方式构建客户端实例:

1
2
3
4
5
HttpClient httpClient = HttpClient.newBuilder()
        .version(HTTP_1_1)
        .proxy(ProxySelector.of(new InetSocketAddress("proxy.mycompany.com", 3128)))
        .authenticator(authenticator)
        .build();

,其中 authenticator 是:

1
2
3
4
5
6
Authenticator authenticator = new Authenticator() {
  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("login","password".toCharArray());
  }
};

然后我自己执行请求:

1
2
3
4
5
6
HttpRequest outRequest = HttpRequest.newBuilder()
        .version(HTTP_1_1)
        .GET()
        .uri(URI.create("https://httpwg.org/asset/http.svg")) // no matter which URI to request
        .build();
HttpResponse<String> inResponse = httpClient.send(outRequest, BodyHandlers.ofString());

但我收到 HTTP 407(需要代理身份验证),而不是来自目标服务器 (https://httpwg.org) 的有效响应,即 HttpClient 不使用提供的 authenticator

我尝试过这里和这里提到的各种解决方案,但都没有帮助。

什么是让它工作的正确方法?


您必须在请求上设置"代理授权"标头。

1
2
3
4
5
6
7
8
9
10
11
12
13
HttpClient httpClient = HttpClient.newBuilder()
        .version(HTTP_1_1)
        .proxy(ProxySelector.of(new InetSocketAddress("proxy.mycompany.com", 3128)))
        .build();

String encoded = new String(Base64.getEncoder().encode("login:password".getBytes()));

HttpRequest outRequest = HttpRequest.newBuilder()
                                    .version(HTTP_1_1)
                                    .GET()
                                    .uri(URI.create("https://httpwg.org/asset/http.svg")) // no matter which URI to request
                                    .setHeader("Proxy-Authorization","Basic" + encoded)
                                    .build();


默认情况下,从 java 8u111 开始,在通过身份验证代理进行隧道传输时,使用代理的基本身份验证被禁用。

您可以通过在 java 命令行中指定 -Djdk.http.auth.tunneling.disabledSchemes="" 来重新启用它。

查看 jdk 8u111 发行说明