您的位置:首页 > 理论基础 > 计算机网络

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

2015-07-23 18:00 489 查看
异常信息如下:

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

 

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[]{};    
        }    
    }    
        
    
}    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: