【问题标题】:How to use HttpsURLConnection through proxy by setProperty?如何通过 setProperty 代理使用 HttpsURLConnection?
【发布时间】:2013-04-02 08:48:31
【问题描述】:

网络环境:

Https 客户端代理服务器Https 服务器
192.168.17.11192.168.17.22
10.100.21.1010.100.21.11

ps: Http Client 没有默认网关,但是可以ping 10.100.21.11

说明:

操作系统:3 台主机上的 Ubuntu 12.04
Https客户端:用java(openjdk-6)实现。有一个网络接口。
代理服务器:Apache2.2。有两个网络接口。
Https服务器:Tomcat6。有一个网络接口。

我使用两种方法通过代理实现httpsurlconnection
(为方便起见,我没有写下用于检查 serverTrustedhostnameVerifier 问题的 ssl 句柄功能。如果需要我会更新。)

1.代理类

InetSocketAddress proxyInet = new InetSocketAddress("10.100.21.11",80);
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyInet);
URL httpsUrl = new URL("https://192.168.17.22:8443/test");
HttpsURLConnection httpsCon = (HttpsURLConnection) httpsUrl.openConnection(proxy);

httpsCon.setDoOutput(true);
httpsCon.setDoInput(true);
httpsCon.setRequestMethod("POST");
OutputStream out = httpsCon.getOutputStream();
OutputStreamWriter owriter = new OutputStreamWriter(out);

owriter.write("<request>test</request>");
owriter.flush();
owriter.close();
...

此方法可行,我观察到数据包流也符合我的预期。
HttpClient ---> ProxyServer ---> HttpServer

但是当我使用 set 属性方法时:

2.setProperty

System.setProperty("http.proxySet", "true");
System.setProperty("http.proxyHost",10.100.21.11);
System.setProperty("http.proxyPort","80");

URL httpsUrl = new URL("https://192.168.17.22:8443/test");
HttpsURLConnection httpsCon = (HttpsURLConnection)httpsUrl.openConnection();

httpsCon.setDoOutput(true);
httpsCon.setDoInput(true);
httpsCon.setRequestMethod("POST");
OutputStream out = httpsCon.getOutputStream();
OutputStreamWriter owriter = new OutputStreamWriter(out);

owriter.write("<request>test</request>");
owriter.flush();
owriter.close();
...

我有一个NoRouteToHostException: Network is unreachable
这让我很困惑。我没有看到 HttpClient 和 ProxyServer 之间的任何数据包。
但是HttpClient可以ping到ProxyServer(10.100.12.10 ping 10.100.21.11)

所以我删除了代理设置(不使用代理):
还得到了NoRouteToHostException: Network is unreachable
我认为这是合理的。因为没有通往外网的路线。

我猜想 setProperty 方法似乎是 httpsUrlConnection 的内部函数将检查此 url 是否可以访问。

但这很奇怪。第一种方法可以成功。

有什么想法吗?或者第一种方法和第二种方法有什么不同?

++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++

更新

System.setProperty("https.proxyHost",10.100.21.11);
System.setProperty("https.proxyPort","80"); 

它可以工作并且数据包流是正确的。
但是设置 https.proxyPort=443 对我来说不可行

System.setProperty("https.proxyPort","443");

它会抛出一个异常,如下所示:

java.net.SocketException: Unexpected end of file from server 
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:770)
....

所以我认为 Apache Proxy 也必须修改为正确的配置。

【问题讨论】:

  • 没有http.proxySet这样的属性。
  • 是的。这个属性真的不用设置。谢谢~

标签: java networking proxy outputstream httpsurlconnection


【解决方案1】:

您的 URL 连接是 https,而您只是设置了 http 代理。

尝试设置 https 代理。

//System.setProperty("https.proxySet", "true"); 
 System.setProperty("https.proxyHost",10.100.21.11);
 System.setProperty("https.proxyPort","443");

编辑 @EJP 是正确的。没有 https.proxySet ..我复制了您的原始问题并包含在答案中。

【讨论】:

  • 没有https.proxySet这样的属性。
  • 我认为这是发送请求“https”url时的正确答案。 setProperty 的 key 是 https.proxyHost/proxyPort 而不是 http.proxyHost/porxyPort。
【解决方案2】:

您需要为其创建一个Proxy 对象。创建一个如下:

Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyServer, Integer.parseInt(proxyPort)));

现在使用此代理创建HttpURLConnection 对象。

HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(proxy);

如果您必须为代理设置凭据,请设置 Proxy-Authorization 请求属性:

String uname_pwd = proxyUsername + ":" + proxyPassword
String authString = "Basic " + new sun.misc.BASE64Encoder().encode(uname_pwd.getBytes())
connection.setRequestProperty("Proxy-Authorization", authString);

最后,你连接:

connection.connect();

【讨论】:

  • 感谢您的回复。首先,我使用第一种方法是创建一个代理对象,它对我来说是可行的。其次,我需要的url是“https”所以我认为使用HttpsURLConnection是正确的。
【解决方案3】:

谢谢@divinedragon!

在 kotlin 上的代码相同:

 fun testProxy(login: String, pass: String, proxyData: ProxyData): String {
    val url = URL("http://api.ipify.org")
    val proxy = Proxy(Proxy.Type.HTTP, InetSocketAddress(proxyData.ip, proxyData.port))
    val connection = url.openConnection(proxy) as HttpURLConnection

    val loginPass = "$login:$pass"
    val encodedLoginPass = Base64.getEncoder().encodeToString(loginPass.toByteArray())
    val authString = "Basic $encodedLoginPass"
    connection.setRequestProperty("Proxy-Authorization", authString);
    with(connection) {
        requestMethod = "GET"  // optional default is GET
        connectTimeout = 2000
        readTimeout = 2000
        return inputStream.bufferedReader().readText()
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 2011-07-09
    • 1970-01-01
    • 2014-01-04
    • 2023-03-16
    相关资源
    最近更新 更多