绕过https安全验证发送post请求

https请求

最近对接客户的需求,要求通过post发送数据给客户端的后台; 特别的地方就是客户的服务器是
https://ip:port/xxxxx  自己弄的https; 没有绑定域名

如果是https绑定了域名就不存在请求的时候安全验证一说了, 但是正式可能是自己弄的时候后, 在发送post数据的时候就需要绕过
https的安全验证了;

这个工能弄了大半天, 借鉴了和多博客的方法, 但是不是很理想;

走过的坑太多了

控制权的请求接口
@RestController
public class HttpsController {


    @RequestMapping(value = "/https", method = RequestMethod.POST)
    public String https(HttpServletRequest request) {
        Enumeration<String> names = request.getParameterNames();
        List<String> lists = new ArrayList<>();
        while (names.hasMoreElements()) {
            lists.add(names.nextElement());
        }
        System.out.println(lists);

        String name = request.getParameter("name");
        Integer age = Integer.valueOf(request.getParameter("age"));
        String content = request.getParameter("content");
        System.out.println(content);
        JSONObject jsonObject = JSONObject.parseObject(content);
        String name2 = jsonObject.get("name").toString();
        Integer age2 = Integer.valueOf(jsonObject.get("age").toString());
        return name + age + " " + content + "  " + name2 + "  " + age2;
    }

}

   spring boot 使用restTemplate的配置
package com.example.study.config;

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.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * @author shenzm
 * @date 2019-9-16 12:12
 * @since 1.0
 */

@Configuration
public class RestTemplateConfig {

    private static final Logger logger = LoggerFactory.getLogger(RestTemplateConfig.class);


    @Bean("httpsRestTemplate")
    public RestTemplate httpsRestTemplate() {
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
        return restTemplate;
    }

    @Bean
    public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
        try {
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] arg, String s) throws CertificateException {
                    return true;
                }
            }).build();

            httpClientBuilder.setSSLContext(sslContext);

            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;

            SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            // 注册http和https请求
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", sslSocketFactory)
                    .build();
            // 开始设置连接池
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            // 最大连接数2700
            connectionManager.setMaxTotal(2700);
            // 同路由并发数100
            connectionManager.setDefaultMaxPerRoute(100);
            //设置连接管理器
            httpClientBuilder.setConnectionManager(connectionManager);
            // 重试次数
            httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));

            CloseableHttpClient httpClient = httpClientBuilder.build();
            // httpClient连接配置
            HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
            // 连接超时150s
            httpRequestFactory.setConnectTimeout(150_000);
            // 数据读取超时时间200s
            httpRequestFactory.setReadTimeout(200_000);
            // 连接不够用的等待时间20s
            httpRequestFactory.setConnectionRequestTimeout(20_000);
            //返回client工厂
            return httpRequestFactory;
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            logger.error("初始化HTTP连接池出错", e);
        }
        return null;
    }
}

    测试类: 三种方式来绕过https安全验证

package com.example.study;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootStudyApplication.class)
@SuppressWarnings("all")
public class HttpClientTest {


    //post 请求地址, 复杂的参数请求: 包含name, age , content 三个参数
    private static final String url = "https://xxxxx:8443/https";


    /**
     * 经过https安全认证处理
     */
    @Autowired
    @Qualifier("httpsRestTemplate")
    RestTemplate restTemplate;


    @Test
    public void sendHttpsRequest() {
        HashMap<String, Object> hashMap = new HashMap<String, Object>();
        hashMap.put("name", "java");
        hashMap.put("age", 18);
        hashMap.put("content", "{\"name\":\"java\",\"age\":\"20\"}");

        MultiValueMap<String, Object> requestParams = new LinkedMultiValueMap<String, Object>();
        requestParams.add("name", "java");
        requestParams.add("age", 18);

        Map<String,Object> temp = new HashMap<String,Object>();
        temp.put("name", "java");
        temp.put("age", 20);
        requestParams.add("content", temp);

        //HttpsURLConnection
        String response = sendPost(url, hashMap);
        System.out.println("HttpsURLConnection : " + response);

        //HttpClient
        String s = doPost(url, hashMap);
        System.out.println("httpClient : " + s);

        //restTemplate
        String result = restTemplate.postForObject(url, requestParams, String.class);
        System.out.println("restTemplate : " + result);
    }


    public static CloseableHttpClient createSSLClientDefault() {
        try {
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());

            // Create all-trusting host name verifier
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };

            // Install the all-trusting host verifier
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, allHostsValid);
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }


    public static String doPost(String url, HashMap<String, Object> params) {
        //构建POST请求   请求地址请更换为自己的。
        HttpPost post = new HttpPost(url);
        InputStream inputStream = null;
        String result = "";
        try {
            //使用之前写的方法创建httpClient实例
            //disableSslVerification();
            CloseableHttpClient httpClient = createSSLClientDefault();
            List<NameValuePair> paramsList = new ArrayList<>();
            for (String key : params.keySet()) {
                paramsList.add(new BasicNameValuePair(key, params.get(key).toString()));
            }
            System.out.println(paramsList);
            post.setEntity(new UrlEncodedFormEntity(paramsList, "UTF-8"));
            post.setHeader("Content-type", "application/x-www-form-urlencoded");
            post.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            HttpResponse response = httpClient.execute(post);
            org.apache.http.HttpEntity responseEntity = response.getEntity();
            if (null != responseEntity && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                inputStream = responseEntity.getContent();
                byte[] buffer = new byte[1024];
                int len;
                StringBuffer sb = new StringBuffer();
                while ((len = inputStream.read(buffer)) != -1) {
                    sb.append(new String(buffer, 0, len, "UTF-8"));
                }
                String content = sb.toString();

                if (content.length() > 0) {
                    return  content;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }


    private static void disableSslVerification() {
        try {
            // Create a trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }
            };

            // Install the all-trusting trust manager
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            // Create all-trusting host name verifier
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };

            // Install the all-trusting host verifier
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }

    private static TrustManager myX509TrustManager = new X509TrustManager() {

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }
    };


    private static String sendPost(String url, Map<String, Object> params) {
        disableSslVerification();
        HttpsURLConnection connection = null;

        List<NameValuePair> param = new ArrayList<>();
        for (String key : params.keySet()) {
            param.add(new BasicNameValuePair(key, params.get(key).toString()));
        }

        try {
            String requestParams = URLEncodedUtils.format(param, "UTF-8");
            URL postUrl = new URL(url + "?" + requestParams);
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            connection = (HttpsURLConnection) postUrl.openConnection();
            connection.setRequestProperty("Content-Type", "application/Json; charset=UTF-8");
            connection.setConnectTimeout(30000);
            connection.setReadTimeout(30000);
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod("POST");    // 默认是 GET方式
            connection.setUseCaches(false);         // Post 请求不能使用缓存
            connection.setInstanceFollowRedirects(true);   //设置本次连接是否自动重定向
            connection.setRequestProperty("User-Agent", "Mozilla/5.0");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.addRequestProperty("Connection", "Keep-Alive");//设置与服务器保持连接
            connection.setRequestProperty("Accept-Language", "zh-CN,zh;0.9");
            connection.connect();
            connection.setSSLSocketFactory(sslcontext.getSocketFactory());


            int responseCode = connection.getResponseCode();
            if (responseCode == 200) {
                final BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                final StringBuffer stringBuffer = new StringBuffer(255);

                synchronized (stringBuffer) {
                    while ((line = in.readLine()) != null) {
                        stringBuffer.append(line);
                        stringBuffer.append("\n");
                    }
                    System.out.println(stringBuffer.toString());
                    return stringBuffer.toString();
                }
            }
            return null;

        } catch (final IOException e) {
            e.printStackTrace();
            return null;
        } catch (final Exception e1) {
            e1.printStackTrace();
            return null;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }


}