Create a tool class that does not authenticate the HTTP client to send HTTPS POST requests, and solve the exception: sun security. validator. ValidatorException: PKIX path vali

Posted by satheshf12000 on Tue, 21 Dec 2021 11:20:06 +0100

The difference between https and http

Reference path: The difference between HTTP and HTTPS
Hypertext Transfer Protocol HTTP protocol is used to transfer information between Web browser and Web server. HTTP protocol sends content in clear text without providing any way of data encryption. If an attacker intercepts the transmission message between Web browser and Web server, he can directly read the information. Therefore, HTTP protocol is not suitable for transmitting some sensitive information, For example: credit card number, password and other payment information.
In order to solve this defect of HTTP protocol, another protocol needs to be used: Secure Socket Layer hypertext transmission protocol HTTPS. For the security of data transmission, HTTPS adds SSL/TLS protocol on the basis of HTTP. SSL/TLS relies on certificates to verify the identity of the server and encrypt the communication between the browser and the server.
HTTPS protocol is a network protocol constructed by SSL/TLS+HTTP protocol, which can carry out encrypted transmission and identity authentication. It is safer than http protocol.
The main functions of HTTPS protocol can be divided into two kinds: one is to establish an information security channel to ensure the security of data transmission; The other is to confirm the authenticity of the website.

Main differences between HTTPS and HTTP

  1. https protocol needs to apply for a certificate from CA. generally, there are few free certificates, so it requires a certain fee.
  2. http is a hypertext transmission protocol, information is plaintext transmission, and https is a secure ssl/tls encrypted transmission protocol.
  3. http and https use completely different connection modes and different ports. The former is 80 and the latter is 443.
  4. http connection is simple and stateless; HTTPS protocol is a network protocol constructed by SSL/TLS+HTTP protocol, which can carry out encrypted transmission and identity authentication. It is safer than http protocol.

Steps for a client to communicate with a Web server using HTTPS
Step 1: the customer uses https URL to access the Web server and requires to establish SSL connection with the Web server.
Step 2: after receiving the client's request, the Web server will send a copy of the certificate information of the website (the certificate contains the public key) to the client.
Step 3: the browser of the client and the Web server begin to negotiate the security level of SSL/TLS connection, that is, the level of information encryption.
Step 4: the browser of the client establishes the session key according to the security level agreed by both parties, and then encrypts the session key with the public key of the website and transmits it to the website.
Step 5: the Web server decrypts the session key with its own private key.
Step 6: the Web server uses the session key to encrypt the communication with the client.

It can be seen from the above that sending an HTTPS request requires a certificate. If there is no certificate in the development program to send an HTTPS request, such an exception will be thrown sun security. validator. ValidatorException: PKIX path validation failed: java. security. cert.CertPathValidatorException: validity check failed. Moreover, our server does not have a certificate. At this time, we need to create a tool class that does not authenticate the HTTP client to send HTTPS POST requests to send requests!
Tools are as follows:

package com.pgl.openApi.util;

import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.HeaderIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
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.conn.ssl.TrustStrategy;
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.message.BasicHeader;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

public class HttpUtils {
	private static Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);

    private static final String HTTP = "http";
    private static final String HTTPS = "https";
    private static SSLConnectionSocketFactory sslsf = null;
    private static PoolingHttpClientConnectionManager cm = null;
    private static SSLContextBuilder builder = null;

    static {
        try {
            builder = new SSLContextBuilder();

            // All trust without identification
            builder.loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                    return true;
                }
            });

            sslsf = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null,
                    NoopHostnameVerifier.INSTANCE);
            Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register(HTTP, new PlainConnectionSocketFactory()).register(HTTPS, sslsf).build();

            cm = new PoolingHttpClientConnectionManager(registry);
            // Maximum connection
            cm.setMaxTotal(2000);
            cm.setDefaultMaxPerRoute(300);//Pay attention to the configuration of multi-threaded call, which is set according to the number of threads
            IdleConnectionEvictor ice = new IdleConnectionEvictor(cm);
            ice.start();
        } catch (Exception e) {
            LOGGER.error("", e);
        }
    }


    public static CloseableHttpClient getHttpClient() throws Exception {
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm)
                .setConnectionManagerShared(true).build();
        return httpClient;
    }

    public static String readHttpResponse(HttpResponse httpResponse) throws ParseException, IOException {
        StringBuilder builder = new StringBuilder();

        // Get response message entity
        HttpEntity entity = httpResponse.getEntity();

        // Response status
        builder.append("status:" + httpResponse.getStatusLine());
        builder.append("headers:");
        HeaderIterator iterator = httpResponse.headerIterator();
        while (iterator.hasNext()) {
            builder.append("\t" + iterator.next());
        }

        // Judge whether the response entity is empty
        if (entity != null) {
            String responseString = EntityUtils.toString(entity);
            builder.append("response length:" + responseString.length());
            builder.append("response content:" + responseString.replace("\r\n", ""));
        }

        return builder.toString();
    }

    public static String sendPost(String url, String content) {
        String result = null;
        CloseableHttpClient httpClient = null;
        try {
            httpClient = getHttpClient();
            HttpPost httpPost = new HttpPost(url);

            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(0).build();
            httpPost.setConfig(requestConfig);
            httpPost.setHeader(new BasicHeader("Connection", "Keep-Alive"));
//            httpPost.setHeader("Content-Type","application/json");
            httpPost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);

            // Set entity priority high
            if (content != null) {
                StringEntity entity = new StringEntity(content);// Solve the problem of Chinese garbled code
//                entity.setContentEncoding("utf-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }

            long startTime = System.currentTimeMillis();
            HttpResponse httpResponse = httpClient.execute(httpPost);
            long endTime = System.currentTimeMillis();
            float seconds = (endTime - startTime) / 1000F;
            LOGGER.info("Call service interface@" + url + "@Total time from request to response:" + seconds + "second");


            int statusCode = httpResponse.getStatusLine().getStatusCode();
            LOGGER.debug("Http Request status:{}", statusCode);
            if (statusCode == HttpStatus.SC_OK) {
                HttpEntity resEntity = httpResponse.getEntity();
                result = EntityUtils.toString(resEntity,"UTF-8");
                LOGGER.debug("Http Request result:{}", result);
            } else {
                readHttpResponse(httpResponse);
            }
        } catch (Exception e) {
            LOGGER.error("Exception calling remote service:\n {}", e);
        }

        return result;
    }

    public static class IdleConnectionEvictor extends Thread {

        private final PoolingHttpClientConnectionManager connectionManager;

        private volatile boolean shutdown;

        public IdleConnectionEvictor(PoolingHttpClientConnectionManager connectionManager) {
            this.connectionManager = connectionManager;
        }

        @Override
        public void run() {
            try {
                while (!shutdown) {
                    synchronized (this) {
                        //Check once every 3s
                        wait(3000);
                        // Close failed connections
                        connectionManager.closeExpiredConnections();
                        // Select to close the link that is idle for 60 seconds
                        connectionManager.closeIdleConnections(60, TimeUnit.SECONDS);
                    }
                }
            } catch (InterruptedException ex) {
                // end
                LOGGER.error("{}",ex);
            }
        }

        public void shutdown() {
            shutdown = true;
            synchronized (this) {
                notifyAll();
            }
        }
    }

}