Java SSL: how to disable hostname verification

前端 未结 5 1146
情深已故
情深已故 2020-11-29 01:54

Is there a way for the standard java SSL sockets to disable hostname verfication for ssl connections with a property? The only way I found until now, is to write a hostname

相关标签:
5条回答
  • 2020-11-29 02:01

    The answer from @Nani doesn't work anymore with Java 1.8u181. You still need to use your own TrustManager, but it needs to be a X509ExtendedTrustManager instead of a X509TrustManager:

    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.Socket;
    import java.net.URL;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLEngine;
    import javax.net.ssl.SSLHandshakeException;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509ExtendedTrustManager;
    
    public class Test {
    
       public static void main (String [] args) throws IOException {
          // This URL has a certificate with a wrong name
          URL url = new URL ("https://wrong.host.badssl.com/");
    
          try {
             // opening a connection will fail
             url.openConnection ().connect ();
          } catch (SSLHandshakeException e) {
             System.out.println ("Couldn't open connection: " + e.getMessage ());
          }
    
          // Bypassing the SSL verification to execute our code successfully
          disableSSLVerification ();
    
          // now we can open the connection
          url.openConnection ().connect ();
    
          System.out.println ("successfully opened connection to " + url + ": " + ((HttpURLConnection) url.openConnection ()).getResponseCode ());
       }
    
       // Method used for bypassing SSL verification
       public static void disableSSLVerification () {
    
          TrustManager [] trustAllCerts = new TrustManager [] {new X509ExtendedTrustManager () {
             @Override
             public void checkClientTrusted (X509Certificate [] chain, String authType, Socket socket) {
    
             }
    
             @Override
             public void checkServerTrusted (X509Certificate [] chain, String authType, Socket socket) {
    
             }
    
             @Override
             public void checkClientTrusted (X509Certificate [] chain, String authType, SSLEngine engine) {
    
             }
    
             @Override
             public void checkServerTrusted (X509Certificate [] chain, String authType, SSLEngine engine) {
    
             }
    
             @Override
             public java.security.cert.X509Certificate [] getAcceptedIssuers () {
                return null;
             }
    
             @Override
             public void checkClientTrusted (X509Certificate [] certs, String authType) {
             }
    
             @Override
             public void checkServerTrusted (X509Certificate [] certs, String authType) {
             }
    
          }};
    
          SSLContext sc = null;
          try {
             sc = SSLContext.getInstance ("SSL");
             sc.init (null, trustAllCerts, new java.security.SecureRandom ());
          } catch (KeyManagementException | NoSuchAlgorithmException e) {
             e.printStackTrace ();
          }
          HttpsURLConnection.setDefaultSSLSocketFactory (sc.getSocketFactory ());
       }
    }
    
    0 讨论(0)
  • 2020-11-29 02:11

    I also had the same problem while accessing RESTful web services. And I their with the below code to overcome the issue:

    public class Test {
        //Bypassing the SSL verification to execute our code successfully 
        static {
            disableSSLVerification();
        }
    
        public static void main(String[] args) {    
            //Access HTTPS URL and do something    
        }
        //Method used for bypassing SSL verification
        public static void disableSSLVerification() {
    
            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) {
                }
    
            } };
    
            SSLContext sc = null;
            try {
                sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
            } catch (KeyManagementException e) {
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };      
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);           
        }
    }
    

    It worked for me. try it!!

    0 讨论(0)
  • 2020-11-29 02:17

    It should be possible to create custom java agent that overrides default HostnameVerifier:

    import javax.net.ssl.*;
    import java.lang.instrument.Instrumentation;
    
    public class LenientHostnameVerifierAgent {
        public static void premain(String args, Instrumentation inst) {
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });
        }
    }
    

    Then just add -javaagent:LenientHostnameVerifierAgent.jar to program's java startup arguments.

    0 讨论(0)
  • 2020-11-29 02:17

    In case you're using apache's http-client 4:

    SSLConnectionSocketFactory sslConnectionSocketFactory = 
        new SSLConnectionSocketFactory(sslContext,
                 new String[] { "TLSv1.2" }, null, new HostnameVerifier() {
                        public boolean verify(String arg0, SSLSession arg1) {
                                return true;
                }
          });
    
    0 讨论(0)
  • 2020-11-29 02:20

    There is no hostname verification in standard Java SSL sockets or indeed SSL, so that's why you can't set it at that level. Hostname verification is part of HTTPS (RFC 2818): that's why it manifests itself as javax.net.ssl.HostnameVerifier, which is applied to an HttpsURLConnection.

    0 讨论(0)
提交回复
热议问题