gpt4 book ai didi

java - 如何以编程方式禁用 Java LDAP JNDI LDAP API 中的证书主机名验证?

转载 作者:太空宇宙 更新时间:2023-11-03 13:14:13 31 4
gpt4 key购买 nike

Java 8u181 引入了一项更改,在使用连接到 LDAPS (TLS) 服务器的 Java JNDI LDAP API 时启用证书主机名验证。

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

如何禁用此主机名验证,或者更好的是指定自定义 javax.net.ssl.HostnameVerifier 类。 Oracle 的文档仅指定了一个 Java 环境属性来禁用验证,但没有说明任何有问题的方法来完成此操作,这对于不能(或不想)更改 JVM 的位/开关的环境至关重要继续运行。

本题:How to disable endpoint identification for java 1.8.181 version问一个类似的问题,但解决方案是通过命令行更改 java 环境。我在问如何在没有环境切换的情况下以编程方式完成它。

关于在 Java 中为其他类型的 SSL 连接禁用主机名验证还有其他问题/答案,但这些答案不适用于 JNDI LDAP API。

最佳答案

正如@Patrick-Mevzek 所说:不要这样做!

但如果你真的必须这样做,你可以这样做:

您需要一个 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”(此版本不需要它,但它仍然可以工作并且不会破坏任何东西)

关于java - 如何以编程方式禁用 Java LDAP JNDI LDAP API 中的证书主机名验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52600211/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com