java调用HTTPS

这两天在做与渠道联调的回调,其中回调渠道的时候使用的是https。

简单的测试代码如下;

 

Java代码  收藏代码

  1. public static void simpleTest(String httpsURL) throws Exception {  
  2.     URL myurl = new URL(httpsURL);  
  3.     HttpsURLConnection con = (HttpsURLConnection) myurl.openConnection();  
  4.     InputStream ins = con.getInputStream();  
  5.     InputStreamReader isr = new InputStreamReader(ins);  
  6.     BufferedReader in = new BufferedReader(isr);  
  7.     String inputLine;  
  8.     while ((inputLine = in.readLine()) != null) {  
  9.         System.out.println(inputLine);  
  10.     }  
  11.     in.close();  
  12. }  

 

但是,如果为自签发的SSL证书(未提供证书发行链而不被信任)的请求地址,上面的代码就不起作用了。

错误为:

 Exception in thread "main" 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。

 

经过查找资料,现有两种解决方案:

1)为自身系统增加证书

 

2)绕过证书验证

 

先来说第一种方案:

1)用IE打开访问的https网址,点击地址栏后面的小锁头(或证书错误标识),查看证书。在弹出的证书信息框中选择第二个页签“详细信息”。点击复制到文件,选择Base64编码的X.509证书导出即可。

2)把证书从其它文件导入到TrustStore文件中。

keytool -import -file D:/test1.cer -keystore D:/crt_test1

执行命令后要求输入密码,记住输入的密码。

 

3)编写如下代码:

 

Java代码  收藏代码

  1. public static void certTest1()throws Exception{  
  2.         String httpsURL = "https://xxx.xxx.cn/";  
  3.         String trustStor="D:/crt_test1";  
  4.         System.setProperty("javax.net.ssl.trustStore", trustStor);  
  5.         URL myurl = new URL(httpsURL);  
  6.         HttpsURLConnection con = (HttpsURLConnection) myurl.openConnection();  
  7.         con.setHostnameVerifier(hv);  
  8.         InputStream ins = con.getInputStream();  
  9.         InputStreamReader isr = new InputStreamReader(ins);  
  10.         BufferedReader in = new BufferedReader(isr);  
  11.         String inputLine=null;  
  12.         while ((inputLine = in.readLine()) != null) {  
  13.             System.out.println(inputLine);  
  14.         }  
  15.         in.close();  
  16. }  
  17. private static HostnameVerifier hv = new HostnameVerifier() {  
  18.         public boolean verify(String urlHostName, SSLSession session) {  
  19.             return urlHostName.equals(session.getPeerHost());  
  20.         }  
  21. };  

 可是如果出现两个https地址并且证书不同的话,上面的代码就没有办法处理了。有人可能说用System.setProperty重新设置一下trustStore,很抱歉,我试了好几次,没有成功。如果他人有成功的请给出代码,谢谢。

 

为了处理两个证书的情况,我又查了下资料,整理一下,使用TrustManager来处理(此时会用到证书的密码)。

代码如下:

Java代码  收藏代码

  1. public static void certTest2(String certDir, String passwd, String urlStr)  
  2.         throws Exception {  
  3.     SSLContext sslContext = SSLContext.getInstance("SSL""SunJSSE");  
  4.     TrustManager[] tms = getTms(certDir, passwd);  
  5.     sslContext.init(null, tms, new java.security.SecureRandom());  
  6.     SSLSocketFactory ssf = sslContext.getSocketFactory();  
  7.   
  8.     URL url = new URL(urlStr);  
  9.     HttpsURLConnection.setDefaultHostnameVerifier(hv);  
  10.     HttpsURLConnection conn = ((HttpsURLConnection) url.openConnection());  
  11.     conn.setSSLSocketFactory(ssf);  
  12.   
  13.     InputStreamReader im = new InputStreamReader(conn.getInputStream(),  
  14.             "GBK");  
  15.     BufferedReader reader = new BufferedReader(im);  
  16.     StringBuffer sb = new StringBuffer();  
  17.     String line = null;  
  18.     while ((line = reader.readLine()) != null) {  
  19.         sb.append(line + "\r\n");  
  20.     }  
  21.     System.out.println(sb);  
  22. }  
  23.   
  24. public static TrustManager[] getTms(String dir, String keyPassword)  
  25.         throws Exception {  
  26.     String talg = TrustManagerFactory.getDefaultAlgorithm();  
  27.     TrustManagerFactory tmFact = TrustManagerFactory.getInstance(talg);  
  28.     FileInputStream tfis = new FileInputStream(dir);  
  29.     KeyStore ts = KeyStore.getInstance("jks");  
  30.     ts.load(tfis, keyPassword.toCharArray());  
  31.     tfis.close();  
  32.     tmFact.init(ts);  
  33.     return tmFact.getTrustManagers();  
  34. }  
  35. private static HostnameVerifier hv = new HostnameVerifier() {  
  36.     public boolean verify(String urlHostName, SSLSession session) {  
  37.         return urlHostName.equals(session.getPeerHost());  
  38.     }  
  39. };  

 再说第二种方案:

不多说,直接上代码

Java代码  收藏代码

  1. public static void withoutCertTest(String urlStr) throws Exception {  
  2.     SSLContext sslContext = SSLContext.getInstance("SSL""SunJSSE");  
  3.     TrustManager[] tms = { ignoreCertificationTrustManger };  
  4.     sslContext.init(null, tms, new java.security.SecureRandom());  
  5.     SSLSocketFactory ssf = sslContext.getSocketFactory();  
  6.   
  7.     URL url = new URL(urlStr);  
  8.     HttpsURLConnection.setDefaultHostnameVerifier(hv);  
  9.     HttpsURLConnection conn = ((HttpsURLConnection) url.openConnection());  
  10.     conn.setSSLSocketFactory(ssf);  
  11.   
  12.     InputStreamReader im = new InputStreamReader(conn.getInputStream(),  
  13.             "GBK");  
  14.     BufferedReader reader = new BufferedReader(im);  
  15.     StringBuffer sb = new StringBuffer();  
  16.     String line = null;  
  17.     while ((line = reader.readLine()) != null) {  
  18.         sb.append(line + "\r\n");  
  19.     }  
  20.     System.out.println(sb);  
  21. }  
  22.   
  23. private static TrustManager ignoreCertificationTrustManger = new X509TrustManager() {  
  24.   
  25.     private X509Certificate[] certificates;  
  26.   
  27.     @Override  
  28.     public void checkClientTrusted(X509Certificate certificates[],  
  29.             String authType) throws CertificateException {  
  30.         if (this.certificates == null) {  
  31.             this.certificates = certificates;  
  32.         }  
  33.     }  
  34.   
  35.     @Override  
  36.     public void checkServerTrusted(X509Certificate[] ax509certificate,  
  37.             String s) throws CertificateException {  
  38.         if (this.certificates == null) {  
  39.             this.certificates = ax509certificate;  
  40.         }  
  41.     }  
  42.   
  43.     @Override  
  44.     public X509Certificate[] getAcceptedIssuers() {  
  45.         return null;  
  46.     }  
  47. };  

 参考网址:

http://guoguanfei.blog.163.com/blog/static/555830372009217115420766/

http://blog.csdn.net/c_4818/article/details/7825388

http://www.wenhq.com/article/view_711.html

 ===========================================================

以上测试以后,与渠道调用的时候并没有成功,于是使用apache提供的HttpClients,问题解决。

代码如下:

Java代码  收藏代码

  1. import java.io.File;  
  2. import java.io.FileInputStream;  
  3. import java.io.IOException;  
  4. import java.net.SocketTimeoutException;  
  5. import java.security.GeneralSecurityException;  
  6. import java.security.cert.CertificateException;  
  7. import java.security.cert.X509Certificate;  
  8. import java.util.ArrayList;  
  9. import java.util.List;  
  10. import java.util.Map;  
  11. import java.util.Map.Entry;  
  12. import java.util.Set;  
  13.   
  14. import javax.net.ssl.SSLContext;  
  15. import javax.net.ssl.SSLException;  
  16. import javax.net.ssl.SSLSession;  
  17. import javax.net.ssl.SSLSocket;  
  18.   
  19. import org.apache.commons.io.IOUtils;  
  20. import org.apache.commons.lang.StringUtils;  
  21. import org.apache.http.Consts;  
  22. import org.apache.http.HttpEntity;  
  23. import org.apache.http.HttpResponse;  
  24. import org.apache.http.NameValuePair;  
  25. import org.apache.http.client.HttpClient;  
  26. import org.apache.http.client.config.RequestConfig;  
  27. import org.apache.http.client.config.RequestConfig.Builder;  
  28. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  29. import org.apache.http.client.methods.HttpGet;  
  30. import org.apache.http.client.methods.HttpPost;  
  31. import org.apache.http.conn.ConnectTimeoutException;  
  32. import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  
  33. import org.apache.http.conn.ssl.SSLContextBuilder;  
  34. import org.apache.http.conn.ssl.TrustStrategy;  
  35. import org.apache.http.conn.ssl.X509HostnameVerifier;  
  36. import org.apache.http.entity.ContentType;  
  37. import org.apache.http.entity.StringEntity;  
  38. import org.apache.http.impl.client.CloseableHttpClient;  
  39. import org.apache.http.impl.client.HttpClients;  
  40. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;  
  41. import org.apache.http.message.BasicNameValuePair;  
  42.   
  43. /** 
  44.  * HttpClientUtils, 使用 HttpClient 4.x<br> 
  45.  *  
  46.  */  
  47. public class HttpClientUtils {  
  48.   
  49.     private static HttpClient client = null;  
  50.     static {  
  51.         PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();  
  52.         cm.setMaxTotal(128);  
  53.         cm.setDefaultMaxPerRoute(128);  
  54.         client = HttpClients.custom().setConnectionManager(cm).build();  
  55.     }  
  56.   
  57.     /** 
  58.      * 发送一个 Post 请求, 使用指定的字符集编码. 
  59.      *  
  60.      * @param url 
  61.      * @param body 
  62.      *            RequestBody 
  63.      * @param mimeType 
  64.      *            例如 application/xml 
  65.      * @param charset 
  66.      *            编码 
  67.      * @param connTimeout 
  68.      *            建立链接超时时间,毫秒. 
  69.      * @param readTimeout 
  70.      *            响应超时时间,毫秒. 
  71.      * @return ResponseBody, 使用指定的字符集编码. 
  72.      *  
  73.      * @throws ConnectTimeoutException 
  74.      *             建立链接超时异常 
  75.      * @throws SocketTimeoutException 
  76.      *             响应超时 
  77.      * @throws Exception 
  78.      */  
  79.     public static String post(String url, String body, String mimeType,  
  80.             String charset, Integer connTimeout, Integer readTimeout)  
  81.             throws ConnectTimeoutException, SocketTimeoutException, Exception {  
  82.         HttpClient client = null;  
  83.         HttpPost post = new HttpPost(url);  
  84.         String result = "";  
  85.         try {  
  86.             if (StringUtils.isNotBlank(body)) {  
  87.                 HttpEntity entity = new StringEntity(body, ContentType.create(  
  88.                         mimeType, charset));  
  89.                 post.setEntity(entity);  
  90.             }  
  91.             // 设置参数  
  92.             Builder customReqConf = RequestConfig.custom();  
  93.             if (connTimeout != null) {  
  94.                 customReqConf.setConnectTimeout(connTimeout);  
  95.             }  
  96.             if (readTimeout != null) {  
  97.                 customReqConf.setSocketTimeout(readTimeout);  
  98.             }  
  99.             post.setConfig(customReqConf.build());  
  100.   
  101.             HttpResponse res;  
  102.             if (url.startsWith("https")) {  
  103.                 // 执行 Https 请求.  
  104.                 client = createSSLInsecureClient();  
  105.                 res = client.execute(post);  
  106.             } else {  
  107.                 // 执行 Http 请求.  
  108.                 client = HttpClientUtils.client;  
  109.                 res = client.execute(post);  
  110.             }  
  111.             result = IOUtils.toString(res.getEntity().getContent(), charset);  
  112.         } finally {  
  113.             post.releaseConnection();  
  114.             if (url.startsWith("https") && client != null  
  115.                     && client instanceof CloseableHttpClient) {  
  116.                 ((CloseableHttpClient) client).close();  
  117.             }  
  118.         }  
  119.         return result;  
  120.     }  
  121.   
  122.     /** 
  123.      * 提交form表单 
  124.      *  
  125.      * @param url 
  126.      * @param params 
  127.      * @param connTimeout 
  128.      * @param readTimeout 
  129.      * @return 
  130.      * @throws ConnectTimeoutException 
  131.      * @throws SocketTimeoutException 
  132.      * @throws Exception 
  133.      */  
  134.     public static String postForm(String url, Map<String, String> params,  
  135.             Map<String, String> headers, Integer connTimeout,  
  136.             Integer readTimeout) throws ConnectTimeoutException,  
  137.             SocketTimeoutException, Exception {  
  138.   
  139.         HttpClient client = null;  
  140.   
  141.         HttpPost post = new HttpPost(url);  
  142.         try {  
  143.             if (params != null && !params.isEmpty()) {  
  144.                 List<NameValuePair> formParams = new ArrayList<org.apache.http.NameValuePair>();  
  145.                 Set<Entry<String, String>> entrySet = params.entrySet();  
  146.                 for (Entry<String, String> entry : entrySet) {  
  147.                     formParams.add(new BasicNameValuePair(entry.getKey(), entry  
  148.                             .getValue()));  
  149.                 }  
  150.                 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(  
  151.                         formParams, Consts.UTF_8);  
  152.                 post.setEntity(entity);  
  153.             }  
  154.             if (headers != null && !headers.isEmpty()) {  
  155.                 for (Entry<String, String> entry : headers.entrySet()) {  
  156.                     post.addHeader(entry.getKey(), entry.getValue());  
  157.                 }  
  158.             }  
  159.             // 设置参数  
  160.             Builder customReqConf = RequestConfig.custom();  
  161.             if (connTimeout != null) {  
  162.                 customReqConf.setConnectTimeout(connTimeout);  
  163.             }  
  164.             if (readTimeout != null) {  
  165.                 customReqConf.setSocketTimeout(readTimeout);  
  166.             }  
  167.             post.setConfig(customReqConf.build());  
  168.             HttpResponse res = null;  
  169.             if (url.startsWith("https")) {  
  170.                 // 执行 Https 请求.  
  171.                 client = createSSLInsecureClient();  
  172.                 res = client.execute(post);  
  173.             } else {  
  174.                 // 执行 Http 请求.  
  175.                 client = HttpClientUtils.client;  
  176.                 res = client.execute(post);  
  177.             }  
  178.             return IOUtils.toString(res.getEntity().getContent(), "UTF-8");  
  179.         } finally {  
  180.             post.releaseConnection();  
  181.             if (url.startsWith("https") && client != null  
  182.                     && client instanceof CloseableHttpClient) {  
  183.                 ((CloseableHttpClient) client).close();  
  184.             }  
  185.         }  
  186.     }  
  187.   
  188.     /** 
  189.      * 发送一个 GET 请求 
  190.      *  
  191.      * @param url 
  192.      * @param charset 
  193.      * @return 
  194.      * @throws Exception 
  195.      */  
  196.     public static String get(String url, String charset) throws Exception {  
  197.         return get(url, charset, nullnull);  
  198.     }  
  199.   
  200.     /** 
  201.      * 发送一个 GET 请求 
  202.      *  
  203.      * @param url 
  204.      * @param charset 
  205.      * @param connTimeout 
  206.      *            建立链接超时时间,毫秒. 
  207.      * @param readTimeout 
  208.      *            响应超时时间,毫秒. 
  209.      * @return 
  210.      * @throws ConnectTimeoutException 
  211.      *             建立链接超时 
  212.      * @throws SocketTimeoutException 
  213.      *             响应超时 
  214.      * @throws Exception 
  215.      */  
  216.     public static String get(String url, String charset, Integer connTimeout,  
  217.             Integer readTimeout) throws ConnectTimeoutException,  
  218.             SocketTimeoutException, Exception {  
  219.         HttpClient client = null;  
  220.   
  221.         HttpGet get = new HttpGet(url);  
  222.         String result = "";  
  223.         try {  
  224.             // 设置参数  
  225.             Builder customReqConf = RequestConfig.custom();  
  226.             if (connTimeout != null) {  
  227.                 customReqConf.setConnectTimeout(connTimeout);  
  228.             }  
  229.             if (readTimeout != null) {  
  230.                 customReqConf.setSocketTimeout(readTimeout);  
  231.             }  
  232.             get.setConfig(customReqConf.build());  
  233.   
  234.             HttpResponse res = null;  
  235.   
  236.             if (url.startsWith("https")) {  
  237.                 // 执行 Https 请求.  
  238.                 client = createSSLInsecureClient();  
  239.                 res = client.execute(get);  
  240.             } else {  
  241.                 // 执行 Http 请求.  
  242.                 client = HttpClientUtils.client;  
  243.                 res = client.execute(get);  
  244.             }  
  245.   
  246.             result = IOUtils.toString(res.getEntity().getContent(), charset);  
  247.         } finally {  
  248.             get.releaseConnection();  
  249.             if (url.startsWith("https") && client != null  
  250.                     && client instanceof CloseableHttpClient) {  
  251.                 ((CloseableHttpClient) client).close();  
  252.             }  
  253.         }  
  254.         return result;  
  255.     }  
  256.   
  257.     /** 
  258.      * 从 response 里获取 charset 
  259.      *  
  260.      * @param ressponse 
  261.      * @return 
  262.      */  
  263.     @SuppressWarnings("unused")  
  264.     private static String getCharsetFromResponse(HttpResponse ressponse) {  
  265.         // Content-Type:text/html; charset=GBK  
  266.         if (ressponse.getEntity() != null  
  267.                 && ressponse.getEntity().getContentType() != null  
  268.                 && ressponse.getEntity().getContentType().getValue() != null) {  
  269.             String contentType = ressponse.getEntity().getContentType()  
  270.                     .getValue();  
  271.             if (contentType.contains("charset=")) {  
  272.                 return contentType  
  273.                         .substring(contentType.indexOf("charset=") + 8);  
  274.             }  
  275.         }  
  276.         return null;  
  277.     }  
  278.   
  279.     private static CloseableHttpClient createSSLInsecureClient()  
  280.             throws GeneralSecurityException {  
  281.         try {  
  282.             SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(  
  283.                     nullnew TrustStrategy() {  
  284.                         public boolean isTrusted(X509Certificate[] chain,  
  285.                                 String authType) throws CertificateException {  
  286.                             return true;  
  287.                         }  
  288.                     }).build();  
  289.             SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(  
  290.                     sslContext, new X509HostnameVerifier() {  
  291.   
  292.                         @Override  
  293.                         public boolean verify(String arg0, SSLSession arg1) {  
  294.                             return true;  
  295.                         }  
  296.   
  297.                         @Override  
  298.                         public void verify(String host, SSLSocket ssl)  
  299.                                 throws IOException {  
  300.                         }  
  301.   
  302.                         @Override  
  303.                         public void verify(String host, X509Certificate cert)  
  304.                                 throws SSLException {  
  305.                         }  
  306.   
  307.                         @Override  
  308.                         public void verify(String host, String[] cns,  
  309.                                 String[] subjectAlts) throws SSLException {  
  310.                         }  
  311.   
  312.                     });  
  313.             return HttpClients.custom().setSSLSocketFactory(sslsf).build();  
  314.         } catch (GeneralSecurityException e) {  
  315.             throw e;  
  316.         }  
  317.     }  
  318.   
  319.     public static void main(String[] args) {  
  320.         try {  
  321.             String xml = IOUtils.toString(new FileInputStream(new File(  
  322.                     "D:\\hongkangtest.txt")));  
  323.             System.out  
  324.                     .println(post(  
  325.                             "https://trade.tongbanjie.com/insurance/callback/hk/redeem.htm",  
  326.                             xml, "html/text""GBK"1000010000));  
  327.         } catch (Exception e) {  
  328.             e.printStackTrace();  
  329.         }  
  330.     }  
  331. }  

 依赖的jar包有:commons-lang-2.6.jar、httpclient-4.3.2.jar、httpcore-4.3.1.jar、commons-io-2.4.jar

 

原文:http://evan0625.iteye.com/blog/2064992

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值