• 技术文章 >后端开发 >C#.Net教程

    httpclient向HTTPS发送数据建立SSL连接时的异常

    巴扎黑巴扎黑2016-12-20 15:08:39原创1136
    异常信息如下:

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    原因:服务器的证书不被信任。一般是这样造成的。

    使用KEYTOOL工具创建证书,然后用TOMCAT启动后,在浏览器打开网站时,会出现证书不被信任的提示。当然,利用HTTPCLIENT向服务端HTTPS发送数据时,HTTPCLIENT也会检测服务端的证书是否被信任,不被信任就抛出上面的异常。

    解决办法有两种,一种是使证书被客户端信任。另一种是使用HTTPCLIENT发送数据时不检测服务器证书是否可信。

    第一种办法,使证书被信任。

    找正规CA签发证书,或者自己签发证书(只能那一台客户机上可信)。找正规CA签发证书就不说了,自己签发证书呢,见我的其他文章。

    我发现,自己签名的证书弄好之后,从客户端打开服务端地址时,不再提示上面的错误,但是还是不能发送数据。原因是什么呢?因为那台证书在客户端操作系统上可信,但是在JAVA的KEYSTORE里不可信,要把服务端的证书导入KEYSTORE库中

    导入办法:

    打开命令行窗口,并到<java-home>\lib\security\ 目录下,运行下面的命令:

    keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file your.cer

    最后一个是服务端导出的证书,其他可以默认。

    要注意的是,如果客户端电脑上装有许多个JAVA版本,要确定你导入的证书的JAVA版本是你TOMCAT使用的那个,一般TOMCAT使用的是环境变量指向的那个JAVA版本。

    如果是在ECLIPSE中建立的TOMCAT服务器,新建时会要你选择默认JRE还是指向的JAVA,这里一定要选指向刚才导入的那个JAVA的路径,不然,你导入的证书库也没效果。

    第二种办法,使用HTTPCLIENT时不检测服务器证书是否可信

    扩展HttpClient 类实现自动接受证书

    因为这种方法自动接收所有证书,因此存在一定的安全问题,所以在使用这种方法前请仔细考虑您的系统的安全需求。具体的步骤如下:

    •提供一个自定义的socket factory (test.MySecureProtocolSocketFactory )。这个自定义的类必须实现接口org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory ,在实现接口的类中调用自定义的X509TrustManager(test.MyX509TrustManager) ,这两个类可以在随本文带的附件中得到

    •创建一个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核实处理。
    上一篇:android 单选(RadioGroup )复选(CheckBox)按钮的应用 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 【c#教程】C# 属性(Property)• 应用绝对路径与相对路径• asp.net 图片验证码的HtmlHelper• C++设计模式浅识策略模式• 从0自学C#04--特性和设计原则
    1/1

    PHP中文网