Как программно отключить проверку имени хоста сертификата в Java LDAP JNDI LDAP API? - PullRequest
0 голосов
/ 02 октября 2018

В Java 8u181 введено изменение, позволяющее проверять имя хоста сертификата при использовании API-интерфейса Java JNDI LDAP, подключающегося к серверам LDAPS (TLS).

См .: https://www.oracle.com/technetwork/java/javase/8u181-relnotes-4479407.html#JDK-8200666

Как можно выполнить проверку имени хостабыть отключенным или, что еще лучше, указать пользовательский класс javax.net.ssl.HostnameVerifier.Документация Oracle только определяет свойство среды Java для отключения проверки, но не указывает какого-либо способа решить эту проблему, что крайне важно для сред, которые не (или не хотят) изменять биты / переключатели JVM, которыми они являются.работает на.

Этот вопрос: Как отключить идентификацию конечной точки для версии Java 1.8.181 Задаёт похожий вопрос, но решение - изменение среды Java через командную строку.Я спрашиваю, как это можно сделать программно без переключения среды.

Существуют другие вопросы / ответы об отключении проверки имени хоста для других типов соединений SSL в Java, но ответы не работают с JNDI LDAP API.

1 Ответ

0 голосов
/ 01 февраля 2019

Как @ Патрик-Мевзек уже сказал: НЕ ДЕЛАЙТЕ ЭТОГО!

Но если вам действительно нужно, вот как вы это сделаете:

Вам нужен SocketFactory, который включает в себяфиктивный TrustManager, который просто игнорирует все что угодно.Существует множество примеров, показывающих, как создать такую ​​вещь.К сожалению, большинство (все?) Из них используют X509TrustManager для этой работы.Это будет работать для недействительных сертификатов, но не будет обрабатывать неправильные или отсутствующие имена хостов.Для этого вам понадобится `` `X509ExtendedTrustManager`:

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedTrustManager;

/**
 * This Socket factory will accept all certificates and all hostnames
 */
public class NonVerifyingSSLSocketFactory extends SocketFactory {
   private static SocketFactory nonVerifyingSSLSochetFactory;

   static {
      TrustManager [] distrustManager = 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) {

         }

         public X509Certificate [] getAcceptedIssuers () {
            return null;
         }

         public void checkClientTrusted (X509Certificate [] c, String a) {
         }

         public void checkServerTrusted (X509Certificate [] c, String a) {
         }
      }};

      try {
         SSLContext sc = SSLContext.getInstance ("SSL");
         sc.init (null, distrustManager, new java.security.SecureRandom ());
         nonVerifyingSSLSochetFactory = sc.getSocketFactory ();
      } catch (GeneralSecurityException e) {
         throw new RuntimeException (e);
      }
   }

   /**
    * This method is needed. It is called by the LDAP Context to create the connection
    *
    * @see SocketFactory#getDefault()
    */
   @SuppressWarnings ("unused")
   public static SocketFactory getDefault () {
      return new NonVerifyingSSLSocketFactory ();
   }

   /**
    * @see SocketFactory#createSocket(String, int)
    */
   public Socket createSocket (String arg0, int arg1) throws IOException {
      return nonVerifyingSSLSochetFactory.createSocket (arg0, arg1);
   }

   /**
    * @see SocketFactory#createSocket(java.net.InetAddress, int)
    */
   public Socket createSocket (InetAddress arg0, int arg1) throws IOException {
      return nonVerifyingSSLSochetFactory.createSocket (arg0, arg1);
   }

   /**
    * @see SocketFactory#createSocket(String, int, InetAddress, int)
    */
   public Socket createSocket (String arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
      return nonVerifyingSSLSochetFactory.createSocket (arg0, arg1, arg2, arg3);
   }

   /**
    * @see SocketFactory#createSocket(InetAddress, int, InetAddress, int)
    */
   public Socket createSocket (InetAddress arg0, int arg1, InetAddress arg2,
                               int arg3) throws IOException {
      return nonVerifyingSSLSochetFactory.createSocket (arg0, arg1, arg2, arg3);
   }

}

. Используйте его в вашей среде InitialLdapContext для его активации:

env.put ("java.naming.ldap.factory.socket", NonVerifyingSSLSocketFactory.class.getName ());

Протестировано с:

  • openjdk версия "1.8.0_191"
  • oraclejdk версия "1.8.0_25" (эта версия не понадобится, но все равно работает и ничего не ломается)
...