httpclient3.1 skips ssl verification

The original old project calls an Http service. Recently, the http service has been adjusted to https, so it needs to be adjusted. Most of the online versions are 4.5 or above, and the 3.1 version has relatively few processing methods, so record it.

1. Implement two classes

1.MyX509TrustManager

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
 
public class MyX509TrustManager implements X509TrustManager {
    /* (non-Javadoc)
    * @see javax.net.ssl.X509TrustManager#checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String)
    */
    public void checkClientTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {
 
    }
    /* (non-Javadoc)
     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String)
     */
    public void checkServerTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {
 
    }
    /* (non-Javadoc)
     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
     */
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

2.MySecureProtocolSocketFactory

The jdk version used in the project is 1.8. The default protocol of the jdk version needs to be specified, so SSLContext context = SSLContext.getInstance(“TLSv1.2”);

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.HttpClientError;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
 
public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory {
 
    //Add an attribute, the main purpose is to obtain SSL and skip verification
    private SSLContext sslContext = null;
    /**
     * Constructor for MySecureProtocolSocketFactory.
     */
    public MySecureProtocolSocketFactory() {
    }
    /**
     * Create a method to obtain SSLContext and import MyX509TrustManager for initialization
     * @return
     */
    private static SSLContext createEasySSLContext() {
        try {
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(null, new TrustManager[] { new MyX509TrustManager() },
                    null);
            return context;
        } catch (Exception e) {
            throw new HttpClientError(e.toString());
        }
    }
 
    /**
     * Determine to obtain SSLContext
     * @return
     */
    private SSLContext getSSLContext() {
        if (this.sslContext == null) {
            this.sslContext = createEasySSLContext();
        }
        return this.sslContext;
    }
    //The following methods basically bring in relevant parameters
    /*
     * (non-Javadoc)
     *
     * @see org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket(java.lang.String,
     * int, java.net.InetAddress, int)
     */
    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
        return getSSLContext().getSocketFactory().createSocket(host, port,clientHost, clientPort);
    }
 
    /*
     * (non-Javadoc)
     *
     * @see org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket(java.lang.String,
     * int, java.net.InetAddress, int,
     * org.apache.commons.httpclient.params.HttpConnectionParams)
     */
    public Socket createSocket(final String host, final int port,final InetAddress localAddress, final int localPort,
                               final HttpConnectionParams params) throws IOException,UnknownHostException, ConnectTimeoutException {
        if (params == null) {
            throw new IllegalArgumentException("Parameters may not be null");
        }
        int timeout = params.getConnectionTimeout();
        if (timeout == 0) {
            return createSocket(host, port, localAddress, localPort);
        } else {
            return ControllerThreadSocketFactory.createSocket(this, host, port,localAddress, localPort, timeout);
        }
    }
 
    /*
     * (non-Javadoc)
     *
     * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
     */
    public Socket createSocket(String host, int port) throws IOException,UnknownHostException {
        return getSSLContext().getSocketFactory().createSocket(host, port);
    }
 
    /*
     * (non-Javadoc)
     *
     * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
     */
    public Socket createSocket(Socket socket, String host, int port,boolean autoClose) throws IOException, UnknownHostException {
        return getSSLContext().getSocketFactory().createSocket(socket, host,port, autoClose);
    }
}

Finally, declare MySecureProtocolSocketFactory to join the Protocol.

 //Statement
        ProtocolSocketFactory fcty = new MySecureProtocolSocketFactory();
        //Add related https request methods
        Protocol.registerProtocol("https", new Protocol("https", fcty, 443));
        //send request
        org.apache.commons.httpclient.HttpClient httpclient = new org.apache.commons.httpclient.HttpClient();
        GetMethod httpget = new GetMethod(url);
        System.out.println("======https service address url:" + url);
        try {
            httpclient.executeMethod(httpget);
            return httpget.getResponseBodyAsString();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new Exception(ex.getMessage());
        } finally {
            httpget.releaseConnection();
        }

After the implementation, I confidently repackaged and updated the official environment, but an error was reported. . .

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates do not conform to algorithm constraints


at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)


at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)


at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)


at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)


at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)


at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)


at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)


at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)


at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)


at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)

Baidu looked at this problem. The certificate does not comply with the algorithm constraints. Basically, the configuration file $JAVA_HOME/jre/lib/security/java.security is modified. However, the project is deployed by docker. The jdk used is the one in docker and the jdk in the external server. The versions are all 11, so it would be too troublesome to have to manually change the configuration every time the service is updated. . .

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

I found an article later, modified the previous implementation class, and rewritten the class I implemented to inherit the new abstract class: X509ExtendedTrustManager. The code is as follows:

//public class MyX509TrustManager implements X509TrustManager {
public class MyX509TrustManager extends X509ExtendedTrustManager {
//Implementation methods, all methods are empty methods
}

Update the code again and the problem is solved!

Reference: httpclient 3.1 skips the verification of https request SSL_Gudou Mao Ning’s blog-CSDN blog
https://www.cnblogs.com/flyingeagle/articles/7508207.html