HttpsUrlConnectionクラスを使用してサーバーに要求を送信しようとしています。サーバーには証明書の問題があるので、すべてを信頼するTrustManagerと同様に寛容なホスト名ベリファイアを設定します。このマネージャーは私の要求を直接行うとうまく動作しますが、プロキシ経由で要求を送信するときにはまったく使用されていないようです。Javaのプロキシ経由でHTTPS要求を送信するにはどうすればよいですか?
は、私はこのような私のプロキシ設定を設定します。
デフォルトのSSLSocketFactoryのためのTrustManagerは、このように設定されてProperties systemProperties = System.getProperties();
systemProperties.setProperty("http.proxyHost", "proxyserver");
systemProperties.setProperty("http.proxyPort", "8080");
systemProperties.setProperty("https.proxyHost", "proxyserver");
systemProperties.setProperty("https.proxyPort", "8080");
:私は、次のコードを実行した場合
SSLContext sslContext = SSLContext.getInstance("SSL");
// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[]
{
new X509TrustManager()
{
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
{
// everything is trusted
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
{
// everything is trusted
}
}
}, new SecureRandom());
// this doesn't seem to apply to connections through a proxy
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
// setup a hostname verifier that verifies everything
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{
public boolean verify(String arg0, SSLSession arg1)
{
return true;
}
});
が、私は終わりますSSLHandshakException( "ハンドシェイク中のリモートホストクローズ接続"):
URL url = new URL("https://someurl");
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", "0");
connection.connect();
私は、SSLを扱う際にプロキシを使用することと何らかの関係がないことを想定しています。プロキシを使用しない場合、私のcheckServerTrustedメソッドが呼び出されます。これは私がプロキシを通って行くときに起こる必要があるものです。
私は通常Javaを扱っていませんし、HTTP/Webのものにはあまり経験がありません。私は自分がしようとしていることを理解するのに必要なすべての詳細を提供していると信じています。そうでない場合は、教えてください。
更新:
ZZコーダによって提案記事を読んだ後、私は、接続コードを次のように変更製:
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setSSLSocketFactory(new SSLTunnelSocketFactory(proxyHost, proxyPort));
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", "0");
connection.connect();
の結果(SSLHandshakeException)は同じです。ここでSLLSocketFactoryをSSLTunnelSocketFactory(この記事で説明したクラス)に設定すると、TrustManagerとSSLContextで行った処理がオーバーライドされます。それでも私はそれを必要としないのですか?
別の更新:
私はすべてを信頼し、私のTrustManagerを使用するのSSLSocketFactoryを使用するようにSSLTunnelSocketFactoryクラスを変更しました。これは何の違いも生じていないようです。これはSSLTunnelSocketFactoryのcreateSocketメソッドです:
public Socket createSocket(Socket s, String host, int port, boolean autoClose)
throws IOException, UnknownHostException
{
Socket tunnel = new Socket(tunnelHost, tunnelPort);
doTunnelHandshake(tunnel, host, port);
SSLSocket result = (SSLSocket)dfactory.createSocket(
tunnel, host, port, autoClose);
result.addHandshakeCompletedListener(
new HandshakeCompletedListener()
{
public void handshakeCompleted(HandshakeCompletedEvent event)
{
System.out.println("Handshake finished!");
System.out.println(
"\t CipherSuite:" + event.getCipherSuite());
System.out.println(
"\t SessionId " + event.getSession());
System.out.println(
"\t PeerHost " + event.getSession().getPeerHost());
}
});
result.startHandshake();
return result;
}
私のコードはconnection.connectを呼び出すと、このメソッドが呼び出され、doTunnelHandshakeへの呼び出しが成功しています。次のコード行では、SSLSocketFactoryを使用してSSLSocketを作成します。この呼び出し後の結果のtoString値である:
"1d49247 [SSL_NULL_WITH_NULL_NULL:ソケット[ADDR =/proxyHost、ポート= proxyPortの、次に、localport = 24372]"。
これは私には意味がありませんが、これが後に崩壊する理由かもしれません。
result.startHandshake()が呼び出されると、呼び出しスタックHttpsClient.afterConnectから同じ引数を使用して、同じcreateSocketメソッドが再度呼び出されます。ただし、Socketがnullである場合を除き、result .startHandshake()を再度実行すると、結果は同じSSLHandshakeExceptionになります。
私はまだますます複雑化しているこのパズルに重要な部分がありませんか?
これは、スタックトレースです:あなたはセキュリティ上の理由から、プロキシであなたのHTTP接続を終了することはできませんので
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:808) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1139) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123) at gsauthentication.SSLTunnelSocketFactory.createSocket(SSLTunnelSocketFactory.java:106) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:391) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133) at gsauthentication.GSAuthentication.main(GSAuthentication.java:52) Caused by: java.io.EOFException: SSL peer shut down incorrectly at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:333) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:789) ... 8 more
あなたは今までにプロキシが接続を閉じましたかどうかを確認しました、プロキシ、すなわち証明書の検証が組み込まれていますか? – sfussenegger
「リモートホストがハンドシェイク中に接続をクローズしました」というエラーメッセージが表示されます。それはプロキシですか、または私がリクエストを送信しようとしているサーバーですか?私は証明書の検証について知らない。 –
クライアントの観点から見ると、私はプロキシもリモートであると考えています。したがって、私は(少なくとも)失敗のポイントとしてプロキシを除外することを確認したいと思います。私は信託店で何か経験があり、時にSSLが苦しいこともあります。しかし、私はそのような例外を見たことはありません。 SSLでプロキシを使用したことはありませんでしたが、最初はプロキシが接続に何の悪影響を及ぼしていないことを確認しましたが、 – sfussenegger