例外情報は次のとおりです:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX パスの構築に失敗しました: sun.security.provider.certpath.SunCertPathBuilderException: 要求されたターゲットへの有効な証明書パスが見つかりません
原因: サーバーの証明書が信頼されていません。これは一般的に引き起こされます。
KEYTOOL ツールを使用して証明書を作成し、それを TOMCAT で起動すると、証明書が信頼されていないことを示すプロンプトが表示されます。もちろん、HTTPCLIENT を使用してサーバー HTTPS にデータを送信する場合、HTTPCLIENT はサーバーの証明書が信頼できるかどうかも検出します。信頼できない場合は、上記の例外がスローされます。
解決策は 2 つあります。1 つは、証明書をクライアントによって信頼されるようにすることです。もう 1 つは、HTTPCLIENT を使用して、サーバー証明書が信頼できるかどうかを確認せずにデータを送信する方法です。
最初の方法は、証明書を信頼できるものにすることです。
証明書を発行する正式な CA を見つけるか、自分で証明書を発行します (証明書はそのクライアントでのみ信頼できます)。証明書を発行するための正式な CA を見つけることについては説明しません。証明書を自分で発行する方法については、私の他の記事を参照してください。
自分で署名した証明書の作成が完了した後、クライアントからサーバーのアドレスを開くと、上記のエラーは表示されなくなりましたが、依然としてデータを送信できないことがわかりました。理由は何ですか?証明書はクライアント オペレーティング システムでは信頼されていますが、JAVA の KEYSTORE では信頼されていないため、サーバーの証明書を KEYSTORE ライブラリにインポートする必要があります
インポート方法:
コマンド ライン ウィンドウを開き、
keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file your.cer
最後の証明書はサーバーによってエクスポートされた証明書で、他の証明書は次のとおりです。債務不履行になる。
クライアント コンピュータに多数の JAVA バージョンがインストールされている場合は、インポートする証明書の JAVA バージョンが TOMCAT で使用されているものであることを確認してください。通常、TOMCAT は が指す JAVA バージョンを使用します。環境変数。
ECLIPSE で作成された TOMCAT サーバーの場合、新しいものを作成するときに、デフォルトの JRE または指定された JAVA を選択するように求められます。それ以外の場合は、インポートしたばかりの JAVA を指すパスを選択する必要があります。インポートしても効果はありません。
2 番目の方法は、HTTPCLIENT を使用するときにサーバー証明書が信頼できるかどうかを確認しないことです
証明書を自動的に受け入れるように HttpClient クラスを拡張します
このメソッドはすべての証明書を自動的に受信するため、特定のセキュリティ上の問題がありますしたがって、この方法を使用する前に、システムのセキュリティ要件を慎重に検討してください。具体的な手順は次のとおりです。
• カスタム ソケット ファクトリ (test.MySecureProtocolSocketFactory) を提供します。このカスタム クラスは、org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory インターフェイスを実装し、そのインターフェイスを実装するクラスでカスタム X509TrustManager (test.MyX509TrustManager) を呼び出す必要があります。これらの 2 つのクラスは、この記事に添付されている添付ファイルで入手できます。
•org.apache.commons.httpclient.protocol.Protocol のインスタンスを作成し、プロトコル名とデフォルトのポート番号を指定します
Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
•作成した https プロトコル オブジェクトを登録します
Protocol.registerProtocol("https ", myhttps);
•その後、通常のプログラミング方法に従って https のターゲット アドレスを開きます。コードは次のとおりです:
MySecureProtocolSocketFactory .java
import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.httpclient.ConnectTimeoutException; import org.apache.commons.httpclient.params.HttpConnectionParams; import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory { private SSLContext sslcontext = null; private SSLContext createSSLContext() { SSLContext sslcontext=null; try { sslcontext = SSLContext.getInstance("SSL"); sslcontext.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } return sslcontext; } private SSLContext getSSLContext() { if (this.sslcontext == null) { this.sslcontext = createSSLContext(); } return this.sslcontext; } public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return getSSLContext().getSocketFactory().createSocket( socket, host, port, autoClose ); } public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return getSSLContext().getSocketFactory().createSocket( host, port ); } public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException { return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort); } public Socket createSocket(String host, int port, InetAddress localAddress, int localPort, HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException { if (params == null) { throw new IllegalArgumentException("Parameters may not be null"); } int timeout = params.getConnectionTimeout(); SocketFactory socketfactory = getSSLContext().getSocketFactory(); if (timeout == 0) { return socketfactory.createSocket(host, port, localAddress, localPort); } else { Socket socket = socketfactory.createSocket(); SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); SocketAddress remoteaddr = new InetSocketAddress(host, port); socket.bind(localaddr); socket.connect(remoteaddr, timeout); return socket; } } //自定义私有类 private static class TrustAnyTrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; } } }