ホームページ  >  記事  >  バックエンド開発  >  httpclient が SSL 接続を確立するために HTTPS にデータを送信する場合の例外

httpclient が SSL 接続を確立するために HTTPS にデータを送信する場合の例外

巴扎黑
巴扎黑オリジナル
2016-12-20 15:08:391723ブラウズ

例外情報は次のとおりです:

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 ライブラリにインポートする必要があります

インポート方法:

コマンド ライン ウィンドウを開き、b875db7abfe6bee43ffba9a229af1b20libsecurity ディレクトリで、次のコマンドを実行します:

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[]{};  
            }  
        }  
          
      
    }


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。