java - 无法在 Java 中将代理身份验证与 Https 一起使用
问题描述
描述
我正在尝试通过需要身份验证的代理连接到使用 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。
解决方案
为了能够通过代理使用 https 连接到 web 服务,我们需要禁用系统属性。
这仅对jdk > 8u11是必需的
在应用程序中设置系统属性将不起作用
private void allowAuthenticationForHttps() {
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
}
它应该在命令行中作为标志传递
-Djdk.http.auth.tunneling.disabledSchemes=""
推荐阅读
- kotlin - 没有静态方法 dispatchUnhandledKeyEventPre
- angular5 - 如何使用 Angular5 使用 *ngIf 检查多个变量?
- facebook - Facebook - 访问其他人在该人时间线上发布的帖子
- android - 删除特定的堆栈活动
- javascript - 如何使用 dropdwon 在文本框中添加或删除多个项目?
- regex - [0-9]* 和 [0-9] 之间的区别
- azure-cosmosdb - 如何让 Cosmos 缩减它创建的分区
- android - android studio中带有两个光标的输入范围
- python - 登录 Django 后将用户重定向到自定义链接
- excel - 如何从我的组合框列表中选择一个值?