web-dev-qa-db-ja.com

setPropertyによるプロキシを介したHttpsURLConnectionの使用方法

ネットワーク環境:

Https Client <=============> Proxy Server <==============> Https Server
192.168.17.11 <----- extranet ------> 192.168.17.22
10.100.21.10 <----イントラネット-----> 10.100.21.11

ps:デフォルトゲートウェイのないHttpクライアントですが、10.100.21.11にpingできます

説明:

OS:3つのホスト上のUbuntu 12.04
Httpsクライアント:Java(openjdk-6)を使用して実装します。ネットワークインターフェイスを1つ用意します。
プロキシサーバー:Apache2.2.2つのネットワークインターフェイスを用意します。
Httpsサーバー:Tomcat6。ネットワークインターフェイスが1つあります。

2つの方法を使用して、プロキシ経由でhttpsurlconnectionを実装します。
(簡単にするため、serverTrustedおよびhostnameVerifierの問題を確認するための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 Propertyメソッドを使用する場合:

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はProxyServerにpingできます(10.100.12.10 ping 10.100.21.11)

したがって、プロキシ設定を削除します(プロキシを使用しない場合)。
またNoRouteToHostException: Network is unreachable
これは合理的だと思いました。エクストラネットへのルートがないためです。

setPropertyメソッドがhttpsUrlConnectionの内部関数がこのURLに到達できるかどうかをチェックする方法だと思います。

しかし、それは奇妙です。最初の方法は成功する可能性があります。

何かアイデアがありますか?または、1番目の方法と2番目の方法の違いは何ですか?

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

更新

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も適切な構成に変更する必要があると考えました。

14
CJeremy

URL接続はhttpsですが、httpプロキシのみを設定しています。

Httpsプロキシを設定してみてください。

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

[〜#〜] edit [〜#〜] @EJPは正しい。 https.proxySetはありません。元の質問をコピーして回答に含めました。

17
Kal

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();
9
divinedragon