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


本文摘自PHP中文网,作者巴扎黑,侵删。

异常信息如下:

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

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

            

        

           

       

    }

相关阅读 >>

c#中五种访问修饰符作用范围实例详解

.net中抽象类实现多态

asp.net在网站根目录下创建文件夹

极客学院c#视频教程的资料推荐

c#中的正则表达式如何验证中文字符的实例

.net是否真的被国内市场嫌弃?

c#怎么将 html转换为图片或 pdf?

.net core使用redis发布订阅方法介绍

.net页面局部更新引发的思考

详细了解在.net core 上运行的wordpress

更多相关阅读请进入《Security》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...