• 使用httpclient工具绕过证书验证进行HTTPS请求


    在项目中需要调用其他服务的接口,该服务需要使用https访问,对此记录了一下,使用httpclient工具绕过证书验证进行HTTPS请求。

    1. 版本1:
      import com.alibaba.fastjson.JSON;
      import org.apache.http.HttpEntity;
      import org.apache.http.client.config.RequestConfig;
      import org.apache.http.client.methods.CloseableHttpResponse;
      import org.apache.http.client.methods.HttpPost;
      import org.apache.http.client.methods.HttpRequestBase;
      import org.apache.http.config.Registry;
      import org.apache.http.config.RegistryBuilder;
      import org.apache.http.conn.socket.ConnectionSocketFactory;
      import org.apache.http.conn.socket.PlainConnectionSocketFactory;
      import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
      import org.apache.http.entity.StringEntity;
      import org.apache.http.impl.client.CloseableHttpClient;
      import org.apache.http.impl.client.HttpClients;
      import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
      import org.apache.http.util.EntityUtils;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      import javax.net.ssl.SSLContext;
      import javax.net.ssl.TrustManager;
      import javax.net.ssl.X509TrustManager;
      import java.io.IOException;
      import java.io.UnsupportedEncodingException;
      import java.net.URI;
      import java.security.cert.CertificateException;
      import java.security.cert.X509Certificate;
      import java.util.Map;
      
      public class HttpClientTest {
      
          private static final Logger logger = LoggerFactory.getLogger(HttpClientTest1.class);
      
      
          /**
           * httpclient绕过证书验证进行HTTPS请求
           * url以https开头,会采用 https单向认证请求
           * yrl以http开头,会使用httpPostRequest
           *
           * @param url
           * @param params  json string
           * @param headers  http header
           * @return
           */
          public static String httpsClientSSLFuntcion(String url, Map<String, Object> headers, String params) throws Exception {
              if (url == null || !url.startsWith("http")) {
                  logger.debug("httpClient发送失败,url异常!");
                  return null;
              }
              //响应内容
              String responseContent = "";
              if (url.startsWith("https")) {
                  CloseableHttpClient httpclient = getHttpClient_ssl();
                  if (httpclient != null) {
                      CloseableHttpResponse response = null;
                      try {
                          HttpPost httpPost = new HttpPost(url);
                          //设置超时,连接超时,获取数据超时
                          RequestConfig requestConfig = RequestConfig.custom()
                                  .setConnectTimeout(10000)
                                  .setSocketTimeout(30000).build();
                          httpPost.setConfig(requestConfig);
                          if (headers != null) {
                              for (Map.Entry<String, Object> param : headers.entrySet()) {
                                  httpPost.addHeader(param.getKey(), param.getValue().toString());
                              }
                          }
                          StringEntity se = new StringEntity(params, "UTF-8");
                          se.setContentType("application/json");
                          httpPost.setEntity(se);
                          response = httpclient.execute(httpPost); //执行POST请求
                          HttpEntity entity = response.getEntity();             //获取响应实体
                          if (null != entity) {
                              responseContent = EntityUtils.toString(entity, "UTF-8");
                              EntityUtils.consume(entity); //Consume response content
                          }
                          response.close();
                      } catch (Exception e) {
                          logger.debug("httpclient发送异常:" + e.getMessage());
                      } finally {
                          try {
                              httpclient.close();
                          } catch (Exception e) {
                              logger.debug("关闭httpclient连接异常:" + e.getMessage());
                          }//关闭连接,释放资源
                      }
                  }
              } else {
                  responseContent = httpPostRequest(url, headers, JSON.toJSONString(params));
              }
              return responseContent;
          }
      
      
          private static CloseableHttpClient getHttpClient_ssl() {
              X509TrustManager xtm = new X509TrustManager() {   //创建TrustManager
                  public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                  }
      
                  public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                  }
      
                  public X509Certificate[] getAcceptedIssuers() {
                      return null;
                  }
      
              };
              SSLContext ctx = null;
              try {
                  ctx = SSLContext.getInstance("TLS");
                  //使用TrustManager来初始化该上下文,TrustManager只是被SSL的Socket所使用
                  ctx.init(null, new TrustManager[]{xtm}, null);
              } catch (Exception e) {
                  logger.debug("httpclient异常");
              }
      
              //创建SSLSocketFactory     new String[] { "TLSv1" }, new String[]{"TLSv1.2"},
              SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
                      ctx,
                      new String[]{"TLS"},
                      null,
                      SSLConnectionSocketFactory.getDefaultHostnameVerifier()
              );
              Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.
                      <ConnectionSocketFactory>create()
                      .register("http", PlainConnectionSocketFactory.getSocketFactory())
                      .register("https", socketFactory)
                      .build();
              // 创建ConnectionManager,添加Connection配置信息
              PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
              CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager)
                      .build();
      
              return closeableHttpClient;
          }
      
      
          /**
           * 发送正常的post请求
           *
           * @param url
           * @param headers Map<String, Object> 请求头
           * @param params  String    参数 json字符串
           * @return String
           * @throws UnsupportedEncodingException
           */
          public static String httpPostRequest(String url, Map<String, Object> headers,
                                               String params) throws Exception {
              HttpPost httpPost = new HttpPost(url);
              try {
                  RequestConfig requestConfig = RequestConfig.custom()
                          .setConnectTimeout(1000).setConnectionRequestTimeout(1000)
                          .setSocketTimeout(2000).build();
                  httpPost.setConfig(requestConfig);
              } catch (Exception e) {
                  return null;
              }
      
              for (Map.Entry<String, Object> param : headers.entrySet()) {
                  httpPost.addHeader(param.getKey(), param.getValue().toString());
              }
              StringEntity se = new StringEntity(params);
              se.setContentType("application/json");
              httpPost.setEntity(se);
      
              return getResult(httpPost);
          }
      
          private static String getResult(HttpRequestBase request) {
              URI uri = request.getURI();
              String urlStr = uri.toString();
              if (urlStr == null || "".equals(urlStr) || !urlStr.startsWith("http")) {
                  return "";
              }
              //不用连接池
              CloseableHttpClient httpClient = HttpClients.custom().build();
              try {
                  CloseableHttpResponse response = httpClient.execute(request);
                  try {
                      HttpEntity entity = response.getEntity();
                      if (entity != null) {
                          String result = EntityUtils.toString(entity, "UTF-8");
                          return result;
                      }
                  } finally {
                      response.close();
                  }
              } catch (Exception e) {
                  logger.error(e.getMessage());
              } finally {
                  try {
                      httpClient.close();
                  } catch (IOException e) {
                      logger.error(e.getMessage());
                  }
              }
      
              return "";
          }
      
      
      }
      

      在使用中调用httpsClientSSLFuntcion方法,但使用中发现报出异常:
       

      java.lang.IllegalArgumentException: TLS
      	at sun.security.ssl.ProtocolVersion.valueOf(ProtocolVersion.java:187)
      	at sun.security.ssl.ProtocolList.convert(ProtocolList.java:84)
      	at sun.security.ssl.ProtocolList.<init>(ProtocolList.java:52)
      	at sun.security.ssl.SSLSocketImpl.setEnabledProtocols(SSLSocketImpl.java:2525)
      	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:371)
      	at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
      	at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
      	at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373)
      	at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
      	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
      	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
      	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
      	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
      	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
      	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
      	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
      	at com.dzh.httpclient.HttpClientTest1.httpsClientSSLFuntcion(HttpClientTest1.java:74)
      	at com.dzh.httpclient.HttpClientTest1.main(HttpClientTest1.java:218)

      发现是TLS版本问题:对方服务器限制只能使用TLSv1.2,但是程序中制定TLS(jdk8以后默认使用TLSv1.2)
      修改后:

    import com.alibaba.fastjson.JSON;
    import org.apache.http.HttpEntity;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.methods.HttpRequestBase;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.util.EntityUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.URI;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import java.util.Map;
    
    public class HttpClientTest {
    
        private static final Logger logger = LoggerFactory.getLogger(HttpClientTest.class);
    
    
        /**
         * http post ,参数中有头信息  分发使用
         *
         * @param url
         * @param headers Map<String, Object> 请求头
         * @param params  String    参数 json字符串
         * @return String
         * @throws UnsupportedEncodingException
         */
        public static String httpPostRequest(String url, Map<String, Object> headers,
                                             String params) throws Exception {
            HttpPost httpPost = new HttpPost(url);
            try {
                RequestConfig requestConfig = RequestConfig.custom()
                        .setConnectTimeout(1000).setConnectionRequestTimeout(1000)
                        .setSocketTimeout(2000).build();
                httpPost.setConfig(requestConfig);
            } catch (Exception e) {
                logger.debug("httpclient发送异常:" + e.getMessage());
                return "0x001";
            }
            for (Map.Entry<String, Object> param : headers.entrySet()) {
                httpPost.addHeader(param.getKey(), param.getValue().toString());
            }
            StringEntity se = new StringEntity(params);
            se.setContentType("application/json");
            httpPost.setEntity(se);
    
            return getResult(httpPost);
        }
    
    
        /**
         * url以https开头,会采用 https单向认证请求
         * yrl以http开头,会使用httpPostRequest
         *
         * @param url
         * @param params Map<String, Object>
         * @return
         */
        public static String httpsClientSSLFuntcion(String url, Map<String, Object> headers, String params) throws Exception {
            if (url == null || !url.startsWith("http")) {
                logger.debug("httpClient发送失败,url异常!");
                return "{"success":"false","message":"httpClient发送失败,url异常!"}";
            }
            String responseContent = "";                     //响应内容
            if (url.startsWith("https")) {
                CloseableHttpClient httpclient = getHttpClient_ssl();
                if (httpclient != null) {
                    CloseableHttpResponse response = null;
                    try {
                        HttpPost httpPost = new HttpPost(url);                        //创建HttpPost
                        //设置超时,连接超时,获取数据超时
                        RequestConfig requestConfig = RequestConfig.custom()
                                .setConnectTimeout(10000)
                                .setSocketTimeout(30000).build();
                        httpPost.setConfig(requestConfig);
                        if (headers != null) {
                            for (Map.Entry<String, Object> param : headers.entrySet()) {
                                httpPost.addHeader(param.getKey(), param.getValue().toString());
                            }
                        }
                        StringEntity se = new StringEntity(params, "UTF-8");
                        se.setContentType("application/json");
                        httpPost.setEntity(se);
                        response = httpclient.execute(httpPost); //执行POST请求
                        HttpEntity entity = response.getEntity();             //获取响应实体
                        if (null != entity) {
                            responseContent = EntityUtils.toString(entity, "UTF-8");
                            EntityUtils.consume(entity); //Consume response content
                        }
                        response.close();
                    } catch (Exception e) {
                        logger.debug("httpclient发送异常:" + e.getMessage());
                    } finally {
                        try {
                            httpclient.close();
                        } catch (IOException e) {
                            logger.debug("关闭httpclient连接异常:" + e.getMessage());
                        }//关闭连接,释放资源
                    }
                }
            } else {
                responseContent = httpPostRequest(url, headers, JSON.toJSONString(params));
            }
            return responseContent;
        }
    
    
        /**
         * 在调用SSL之前需要重写验证方法,取消检测SSL
         * 创建ConnectionManager,添加Connection配置信息
         *
         * @return HttpClient 支持https
         */
        private static CloseableHttpClient getHttpClient_ssl() {
            X509TrustManager xtm = new X509TrustManager() {   //创建TrustManager
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }
    
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }
    
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
    
            };
            //TLS1.0与SSL3.0基本上没有太大的差别,可粗略理解为TLS是SSL的继承者,但它们使用的是相同的SSLContext
            SSLContext ctx = null;
            try {
                ctx = SSLContext.getInstance("TLS");
                //使用TrustManager来初始化该上下文,TrustManager只是被SSL的Socket所使用
                ctx.init(null, new TrustManager[]{xtm}, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.
                    <ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", socketFactory)
                    .build();
            // 创建ConnectionManager,添加Connection配置信息
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager)
                    .build();
    
    
            return closeableHttpClient;
        }
    
    
        private static String getResult(HttpRequestBase request) {
            URI uri = request.getURI();
            String urlStr = uri.toString();
            if (urlStr == null || "".equals(urlStr) || !urlStr.startsWith("http")) {
                return "0x001";
            }
            //不用连接池
            CloseableHttpClient httpClient = HttpClients.custom().build();
            try {
                CloseableHttpResponse response = httpClient.execute(request);
                try {
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        String result = EntityUtils.toString(entity, "UTF-8");
                        return result;
                    }
                } finally {
                    response.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
            } finally {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    logger.error(e.getMessage());
                }
            }
    
            return "0x001";
        }
    
    
    }
    
  • 相关阅读:
    python初步学习-查看文档及数据类型转换
    python初步学习-python数据类型-集合(set)
    python初步学习-python数据类型-字典(dict)
    python初步学习-python数据类型-列表(list)
    python初步学习-python数据类型之strings(字符串)
    python初步学习-python数据类型之number(数值)
    python初步学习-python运算符
    python初步学习-pycharm使用 (二)
    python初步学习-pycharm使用
    yarn npm 镜像切换
  • 原文地址:https://www.cnblogs.com/dingzuoheng/p/12805058.html
Copyright © 2020-2023  润新知