Java SSL:如何禁用主机名验证

paw*_*que 35 java ssl hostname ssl-certificate

有没有办法让标准的java SSL套接字禁用与属性的ssl连接的主机名验证?我到目前为止找到的唯一方法是编写一个主机名验证程序,它始终返回true.

Weblogic提供了这种可能性,可以使用以下属性禁用主机名验证:

-Dweblogic.security.SSL.ignoreHostnameVerify

Vad*_*zim 27

应该可以创建覆盖默认值的自定义java代理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;
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

然后只需添加-javaagent:LenientHostnameVerifierAgent.jar到程序的java启动参数.

  • 这可能是处理它的好方法,但我正在处理 Apache 的 http 客户端。我如何创建一个 javaagent 来设置 `SSLSocketFactory.setHostnameVerifier(new AllowAllHostnameVerifier())`? (2认同)
  • 请记住添加带有“Premain-Class: LenientHostnameVerifierAgent”的清单 (2认同)

小智 8

@Nani 的答案不再适用于 Java 1.8u181。你仍然需要使用你自己的 TrustManager,但它需要是一个X509ExtendedTrustManager而不是一个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 ());
   }
}
Run Code Online (Sandbox Code Playgroud)

  • **警告**:此答案中的解决方案似乎禁用了所有信任验证,而帖子中没有太多警告(如果您在代码中排除“trustAllCerts”)。 (2认同)

use*_*421 6

标准Java SSL套接字或SSL中没有主机名验证,因此您无法在该级别设置它.主机名验证是HTTPS(RFC 2818)的一部分:这就是为什么它将自身显示为javax.net.ssl.HostnameVerifier,它应用于HttpsURLConnection.

  • 他们根本没有修辞,我试图了解ssl的工作原理并理解jdk和weblogic之间的区别.也许是有原因的. (4认同)

Nan*_*ani 5

我在访问 RESTful Web 服务时也遇到了同样的问题。我用下面的代码来克服这个问题:

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);           
    }
}
Run Code Online (Sandbox Code Playgroud)

它对我有用。尝试一下!!

  • 这不安全地信任所有证书,但它不会绕过主机名验证,因此它不会回答问题。 (11认同)