HTTPS and self-signed certificate issue

前端 未结 3 1805
無奈伤痛
無奈伤痛 2020-12-08 18:14

I have to use HTTPS for sending POST requests to a server (using a self-signed certificate). This is how I do it:

HttpClient httpClient = getHttpClient();

f         


        
相关标签:
3条回答
  • 2020-12-08 18:22

    for self documenting and to help others resolve the imports on accepted the answers (which works for me but spend time testing the imports between java., javax. and org.apache.http.*):

    import java.io.IOException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.apache.http.HttpVersion;
    import org.apache.http.client.HttpClient;
    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
    import org.apache.http.params.HttpConnectionParams;
    import org.apache.http.params.HttpParams;
    import org.apache.http.params.HttpProtocolParams;
    
    0 讨论(0)
  • 2020-12-08 18:26

    I finally solved it, using a custom subclass of SSLSocketFactory:

    public class CustomSSLSocketFactory extends SSLSocketFactory {
    
        private SSLContext sslContext = SSLContext.getInstance("TLS");
    
        public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
    
            super(truststore);
    
            TrustManager tm = new X509TrustManager() {
    
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws certificateException {
            }
    
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }
    
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
    
            };
    
            sslContext.init(null, new TrustManager[] {tm}, null);
    
        }
    
        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        }
    
        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    
    }
    

    And I use it as follows:

    public HttpClient getHttpClient() {
    
        DefaultHttpClient client = null;
    
        try {
    
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
    
            SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
            // Setting up parameters
            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, "utf-8");
            params.setBooleanParameter("http.protocol.expect-continue", false);
    
            // Setting timeout
            HttpConnectionParams.setConnectionTimeout(params, TIMEOUT);
            HttpConnectionParams.setSoTimeout(params, TIMEOUT);
    
            // Registering schemes for both HTTP and HTTPS
            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            registry.register(new Scheme("https", sf, 443));
    
            // Creating thread safe client connection manager
            ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
    
            // Creating HTTP client
            client = new DefaultHttpClient(ccm, params);
    
            // Registering user name and password for authentication
            client.getCredentialsProvider().setCredentials(
                    new AuthScope(null, -1),
                    new UsernamePasswordCredentials(mUsername, mPassword));
    
        } catch (Exception e) {
            client = new DefaultHttpClient();
        }
    
        return client;
    
    }
    

    Don't know why the other solutions I found did not work for me...

    0 讨论(0)
  • 2020-12-08 18:31

    try this before performing the request

        SSLSocketFactory ssl =  (SSLSocketFactory)http.getConnectionManager().getSchemeRegistry().getScheme( "https" ).getSocketFactory(); 
        ssl.setHostnameVerifier( SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER );
    
    0 讨论(0)
提交回复
热议问题