httpclient向HTTPS发送数据建立SSL连接时的错误

来源:互联网 发布:安卓解压软件 编辑:程序博客网 时间:2024/06/18 09:08
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

 

your.cer是服务端导出的证书,其他可以默认。

 

第二种办法,使用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 的目标地址,代码如下:

TestMain.java

package com.test.https;import java.util.HashMap;import java.util.Map;import org.apache.http.HttpEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;public class TestMain {private String url = "https://www.nuomi.com/?cid=002540";      private String charset = "gbk";      private HttpClientUtil httpClientUtil = null;            public TestMain(){            httpClientUtil = new HttpClientUtil();      }            public void test(){           String sourceUrl = url;               String httpOrgCreateTestRtn = httpClientUtil.doPost(sourceUrl,null,charset);          System.out.println("result:"+httpOrgCreateTestRtn);        }            public static void main(String[] args){          TestMain main = new TestMain();          main.test();      }  }

HttpClientUtil.jva

package com.test.https;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Map.Entry;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.NameValuePair;import org.apache.http.client.HttpClient;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;public class HttpClientUtil { public String doPost(String url,Map<String,String> map,String charset){          HttpClient httpClient = null;          HttpGet  httpGet = null;        String result = null;          try{                    httpClient = new SSLClient();              httpGet = new HttpGet(url);                     HttpResponse response = httpClient.execute(httpGet);              if(response != null){                            HttpEntity resEntity = response.getEntity();                  if(resEntity != null){                                      result = EntityUtils.toString(resEntity,charset);                  }              }                      }catch(Exception ex){                    ex.printStackTrace();          }          return result;      }  }
SSLClient.java
package com.test.https;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager;import javax.net.ssl.X509TrustManager;import org.apache.http.conn.ClientConnectionManager;import org.apache.http.conn.scheme.Scheme;import org.apache.http.conn.scheme.SchemeRegistry;import org.apache.http.conn.ssl.SSLSocketFactory;import org.apache.http.impl.client.DefaultHttpClient;public class SSLClient extends DefaultHttpClient{@SuppressWarnings("deprecation")public SSLClient() throws Exception{          super();          SSLContext ctx = SSLContext.getInstance("TLS");          X509TrustManager tm = new X509TrustManager() {                  @Override                  public void checkClientTrusted(X509Certificate[] chain,                          String authType) throws CertificateException {                  }                  @Override                  public void checkServerTrusted(X509Certificate[] chain,                          String authType) throws CertificateException {                  }                  @Override                  public X509Certificate[] getAcceptedIssuers() {                      return null;                  }          };          ctx.init(null, new TrustManager[]{tm}, null);          SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);          ClientConnectionManager ccm = this.getConnectionManager();          SchemeRegistry sr = ccm.getSchemeRegistry();          sr.register(new Scheme("https", 443, ssf));      }  }


0 0
原创粉丝点击