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

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/huashanlunjian/article/details/83950231

异常信息如下:

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 factorytest.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[]{};  
            }  
        }  
          
      
    }  
 
展开阅读全文

建立与服务器的连接时出错?

08-31

很急,请高手帮忙解决?rnrn我的数据库放在另一台机器上了,为什么我现在连接不到她了,问题是我先连上过,后来那台机器重装了系统就连不上了.报下面的错误:rnrnrnrn在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接) rn说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 rnrn异常详细信息: System.Data.SqlClient.SqlException: 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接)rnrn源错误: rnrn执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。 rnrn堆栈跟踪: rnrnrn[SqlException (0x80131904): 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接)]rn Admin.DynamicQuery.Load(String conjuction) +239rn Admin.User.CheckPassword(String userID, String password, String& errorMsg, UserAuthority& userAuth) +613rn Admin_Login.btn_Login_Click(Object sender, EventArgs e) +369rn System.Web.UI.WebControls.Button.OnClick(EventArgs e) +105rn System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +107rn System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +7rn System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +11rn System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +33rn System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5102rnrn rn 论坛

关于httpclient访问httpsssl证书问题

12-27

[b]我用httpclient访问一个https的网站,我在网上找了一个这个类[/b]import java.io.IOException;rnimport java.net.InetAddress;rnimport java.net.InetSocketAddress;rnimport java.net.Socket;rnimport java.net.SocketAddress;rnimport java.net.UnknownHostException;rnimport java.security.KeyManagementException;rnimport java.security.NoSuchAlgorithmException;rnimport java.security.cert.CertificateException;rnimport java.security.cert.X509Certificate;rnrnimport javax.net.SocketFactory;rnimport javax.net.ssl.SSLContext;rnimport javax.net.ssl.TrustManager;rnimport javax.net.ssl.X509TrustManager;rnrnimport org.apache.commons.httpclient.ConnectTimeoutException;rnimport org.apache.commons.httpclient.params.HttpConnectionParams;rnimport org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;rnrnpublic class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory rn staticrn System.out.println(">>>>in MySecureProtocolSocketFactory>>");rn rn private SSLContext sslcontext = null;rn rn public SSLContext createSSLContext() rn SSLContext sslcontext=null;rn try rn sslcontext = SSLContext.getInstance("SSL");rn sslcontext.init(null, new TrustManager[]new TrustAnyTrustManager(), new java.security.SecureRandom());rn catch (NoSuchAlgorithmException e) rn e.printStackTrace();rn catch (KeyManagementException e) rn e.printStackTrace();rn rn return sslcontext;rn rn rn public SSLContext getSSLContext() rn if (this.sslcontext == null) rn this.sslcontext = createSSLContext();rn rn return this.sslcontext;rn rn rn public Socket createSocket(Socket socket, String host, int port, boolean autoClose)rn throws IOException, UnknownHostException rn return getSSLContext().getSocketFactory().createSocket(rn socket,rn host,rn port,rn autoClosern );rn rnrn public Socket createSocket(String host, int port) throws IOException,rn UnknownHostException rn return getSSLContext().getSocketFactory().createSocket(rn host,rn portrn );rn rn rn rn public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort)rn throws IOException, UnknownHostException rn return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);rn rnrn public Socket createSocket(String host, int port, InetAddress localAddress,rn int localPort, HttpConnectionParams params) throws IOException,rn UnknownHostException, ConnectTimeoutException rn if (params == null) rn throw new IllegalArgumentException("Parameters may not be null");rn rn int timeout = params.getConnectionTimeout();rn SocketFactory socketfactory = getSSLContext().getSocketFactory();rn if (timeout == 0) rn return socketfactory.createSocket(host, port, localAddress, localPort);rn else rn Socket socket = socketfactory.createSocket();rn SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);rn SocketAddress remoteaddr = new InetSocketAddress(host, port);rn socket.bind(localaddr);rn socket.connect(remoteaddr, timeout);rn return socket;rn rn rn rn //自定义私有类rn private static class TrustAnyTrustManager implements X509TrustManager rn rn public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException rn rn rn public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException rn rn rn public X509Certificate[] getAcceptedIssuers() rn return new X509Certificate[];rn rn rn rnrnrnrn[b]用这个类可以访问到那个https的网站,我模拟了一个用户登录过程,但一旦登录完就自动退出。以前是可以用这个方法登录进那个网站的,但现在却不行了,不知是何故,请高手指教!!![/b] 论坛

建立socket链接时发送数据失败

02-24

目的:与服务器建立Socket链接,向其发送数据并接受返回的数据rn问题:数据发送失败(注:是通过发送数据后的没有效果判断的,不是通过catch与捕获异常判断),麻烦大神帮我看看问题出在哪,代码如下:rnprotected void SenderMessageToServer(String SenderMessage)rn rn byte[] result = new byte[1024];rn IPAddress ip = IPAddress.Parse(服务器IP地址);rn Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);rn tryrn rn clientSocket.Connect(new IPEndPoint(ip, 服务器端口)); //配置服务器IP与端口 rn HtmlGenericControl Backstagediv1 = new HtmlGenericControl("div");rn System.Web.UI.WebControls.Label CmdID1 = new System.Web.UI.WebControls.Label();rn CmdID1.Text = "连接服务器成功";rn PlaceHolder.Controls.Add(Backstagediv1);rn PlaceHolder.Controls.Add(CmdID1);rn rn catchrn rn HtmlGenericControl Backstagediv2 = new HtmlGenericControl("div");rn System.Web.UI.WebControls.Label CmdID2 = new rnSystem.Web.UI.WebControls.Label();rn CmdID2.Text = "连接服务器失败";rn PlaceHolder.Controls.Add(Backstagediv2);rn PlaceHolder.Controls.Add(CmdID2);rn //Console.WriteLine("连接服务器失败,请按回车键退出!");rn return;rn rn string sendMessage = SenderMessage + "\0";rn //通过 clientSocket 发送数据 rn tryrn rn string revmsg; //接受服务器返回的信息rn byte[] msg = Encoding.ASCII.GetBytes(sendMessage); //发送给服务器的数据rn clientSocket.Send(msg); //发送数据rn int receiveLength = clientSocket.Receive(result);rn revmsg = Encoding.ASCII.GetString(result);rn HtmlGenericControl Backstagediv3 = new HtmlGenericControl("div");rn System.Web.UI.WebControls.Label CmdID3 = new System.Web.UI.WebControls.Label();rn CmdID3.Text = "发送数据成功,服务器返回数据:" +revmsg; rn PlaceHolder.Controls.Add(Backstagediv3);rn PlaceHolder.Controls.Add(CmdID3);rn rn catch (Exception expectiinmessage)rn rn clientSocket.Shutdown(SocketShutdown.Both);rn clientSocket.Close();rn HtmlGenericControl Backstagediv3 = new HtmlGenericControl("div");rn System.Web.UI.WebControls.Label CmdID3 = new System.Web.UI.WebControls.Label();rn CmdID3.Text = "发送数据失败,服务器返回异常数据:" + expectiinmessage;rn PlaceHolder.Controls.Add(Backstagediv3);rn PlaceHolder.Controls.Add(CmdID3);rn return;rn rnrn 论坛

System.Data.SqlClient.SqlException: 在建立与服务器的连接时出错。

04-28

winxp+sqlserver2000,sqlserver2000和程序是在两台机器上;在网上搜的东西也没有解决问题;rn请教:rnrnrnSystem.Data.SqlClient.SqlException: 在建立与服务器的连接时出错。在连接到 SQL Server 2005 时,在默认的设置下 SQL Server 不允许进行远程连接可能会导致此失败。 (provider: 命名管道提供程序, error: 40 - 无法打开到 SQL Server 的连接) 在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) 在 System.Data.SqlClient.TdsParser.Connect(Boolean& useFailoverPartner, Boolean& failoverDemandDone, String host, String failoverPartner, String protocol, SqlInternalConnectionTds connHandler, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, SqlConnection owningObject, Boolean aliasLookup) 在 System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) 在 System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance) 在 System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) 在 System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) 在 System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject) 在 System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject) 在 System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) 在 System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) 在 System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) 在 System.Data.SqlClient.SqlConnection.Open() 论坛

没有更多推荐了,返回首页