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。
我尝试过这里和这里提到的各种解决方案,但都没有帮助。
什么是让它工作的正确方法?
- 它似乎在访问 http 站点时有效,但不是 https。您找到任何解决方案了吗?
- @Keijack,对于那个特定的应用程序,我不得不使用 Apache HTTP 客户端,因为它是唯一能够处理 NTLM 身份验证的客户端。但我仍然想知道如何使它与 JDK HttpClient 一起工作。
您必须在请求上设置”代理授权”标头。
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() |
- 在 System.setProperty(“jdk.http.auth.tunneling.disabledSchemes”??,””); 之后并且如果代理使用基本授权,则此方法有效。
- @hbelmiro,最后我不得不使用另一个 HTTP 客户端,所以我没有检查你的答案。但还是谢谢你!
- 我确认它适用于 Java 11,并假设系统属性”jdk.http.auth.tunneling.disabledSchemes”不包括”基本”。
- 应该注意的是,这样做有效地绕过了 JDK 提供的 Authenticator API。由于基本身份验证非常简单,这是一个直接的解决方案。我观察到相同的行为,我很好奇为什么记录的解决方案不起作用,并将其追溯到我的公司代理服务器在 Proxy-Authenticate 标头中返回多个值,其中一个是 Basic 但 AuthenticationFilter.response() 会静默如果返回的第一个标头不是 Basic,则无法应用任何身份验证。
默认情况下,从 java 8u111 开始,在通过身份验证代理进行隧道传输时,使用代理的基本身份验证被禁用。
您可以通过在 java 命令行中指定 -Djdk.http.auth.tunneling.disabledSchemes=”” 来重新启用它。
查看 jdk 8u111 发行说明
- 它看起来像解决方案,但由于某种原因不起作用……我尝试使用相关的 jdk.http.auth.proxying.disabledSchemes 标志,但它也没有效果。
- 代理和服务器是否都需要身份验证,如果需要,它们是否需要不同的凭据?如果是这种情况,那么您的身份验证器需要在返回适当的凭据之前考虑主机/地址。此外,您可能需要检查代理是否请求基本身份验证,因为这是堆栈默认支持的唯一方案。
- 丹尼尔,是的,在这种特殊情况下,代理和服务器都需要身份验证。我尝试将调试器断点放入 Authenticator 代码中,但没有一个触发,因此它所针对的主机/地址没有区别。然后我深入研究了流量转储,发现目前这个代理不请求基本身份验证方案(但只请求 NTLM 和协商)。为了确认这一点,我使用了 Apache HTTP 客户端,它成功地处理了 NTLM 身份验证。将进一步调查。感谢您的时间!
来源:https://www.codenong.com/53333556/