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

异常信息如下:

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代码 :
  1. import java.io.IOException;     
  2. import java.net.InetAddress;     
  3. import java.net.InetSocketAddress;     
  4. import java.net.Socket;     
  5. import java.net.SocketAddress;     
  6. import java.net.UnknownHostException;     
  7. import java.security.KeyManagementException;     
  8. import java.security.NoSuchAlgorithmException;     
  9. import java.security.cert.CertificateException;     
  10. import java.security.cert.X509Certificate;     
  11.      
  12. import javax.net.SocketFactory;     
  13. import javax.net.ssl.SSLContext;     
  14. import javax.net.ssl.TrustManager;     
  15. import javax.net.ssl.X509TrustManager;     
  16.      
  17. import org.apache.commons.httpclient.ConnectTimeoutException;     
  18. import org.apache.commons.httpclient.params.HttpConnectionParams;     
  19. import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;     
  20.      
  21. public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory {     
  22.     private SSLContext sslcontext = null;     
  23.          
  24.     private SSLContext createSSLContext() {     
  25.         SSLContext sslcontext=null;     
  26.         try {     
  27.             sslcontext = SSLContext.getInstance("SSL");     
  28.             sslcontext.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());     
  29.         } catch (NoSuchAlgorithmException e) {     
  30.             e.printStackTrace();     
  31.         } catch (KeyManagementException e) {     
  32.             e.printStackTrace();     
  33.         }     
  34.         return sslcontext;     
  35.     }     
  36.          
  37.     private SSLContext getSSLContext() {     
  38.         if (this.sslcontext == null) {     
  39.             this.sslcontext = createSSLContext();     
  40.         }     
  41.         return this.sslcontext;     
  42.     }     
  43.          
  44.     public Socket createSocket(Socket socket, String host, int port, boolean autoClose)     
  45.             throws IOException, UnknownHostException {     
  46.         return getSSLContext().getSocketFactory().createSocket(     
  47.                 socket,     
  48.                 host,     
  49.                 port,     
  50.                 autoClose     
  51.             );     
  52.     }     
  53.      
  54.     public Socket createSocket(String host, int port) throws IOException,     
  55.             UnknownHostException {     
  56.         return getSSLContext().getSocketFactory().createSocket(     
  57.                 host,     
  58.                 port     
  59.             );     
  60.     }     
  61.          
  62.          
  63.     public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)     
  64.             throws IOException, UnknownHostException {     
  65.         return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);     
  66.     }     
  67.      
  68.     public Socket createSocket(String host, int port, InetAddress localAddress,     
  69.             int localPort, HttpConnectionParams params) throws IOException,     
  70.             UnknownHostException, ConnectTimeoutException {     
  71.         if (params == null) {     
  72.             throw new IllegalArgumentException("Parameters may not be null");     
  73.         }     
  74.         int timeout = params.getConnectionTimeout();     
  75.         SocketFactory socketfactory = getSSLContext().getSocketFactory();     
  76.         if (timeout == 0) {     
  77.             return socketfactory.createSocket(host, port, localAddress, localPort);     
  78.         } else {     
  79.             Socket socket = socketfactory.createSocket();     
  80.             SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);     
  81.             SocketAddress remoteaddr = new InetSocketAddress(host, port);     
  82.             socket.bind(localaddr);     
  83.             socket.connect(remoteaddr, timeout);     
  84.             return socket;     
  85.         }     
  86.     }     
  87.          
  88.     //自定义私有类     
  89.     private static class TrustAnyTrustManager implements X509TrustManager {     
  90.             
  91.         public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {     
  92.         }     
  93.         
  94.         public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {     
  95.         }     
  96.         
  97.         public X509Certificate[] getAcceptedIssuers() {     
  98.             return new X509Certificate[]{};     
  99.         }     
  100.     }     
  101.          
  102.      
  103. }    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值