jndi LDAPS custom HostnameVerifier and TrustManager(jndi LDAPS 自定义 HostnameVerifier 和 TrustManager)
问题描述
我们正在编写一个连接到不同 LDAP 服务器的应用程序.对于每台服务器,我们可能只接受某个证书.该证书中的主机名无关紧要.当我们使用 LDAP 和 STARTTLS 时,这很容易,因为我们可以使用 StartTlsResponse.setHostnameVerifier(..-)
并使用 StartTlsResponse.negotiate(...)
匹配SSLSocketFactory
.但是,我们还需要支持 LDAPS 连接.Java 本机支持这一点,但前提是服务器证书受默认 java 密钥库信任.虽然我们可以替换它,但我们仍然不能为不同的服务器使用不同的密钥库.
We are writing an application that shall connect to different LDAP servers. For each server we may only accept a certain certificate. The hostname in that certificate shall not matter. This is easy, when we use LDAP and STARTTLS, because we can use StartTlsResponse.setHostnameVerifier(..-)
and use StartTlsResponse.negotiate(...)
with a matching SSLSocketFactory
. However we also need to support LDAPS connections. Java supports this natively, but only if the server certificate is trusted by the default java keystore. While we could replace that, we still cannot use different keystores for different servers.
现有的连接代码如下:
Hashtable<String,String> env = new Hashtable<String,String>();
env.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" );
env.put( Context.PROVIDER_URL, ( encryption == SSL ? "ldaps://" : "ldap://" ) + host + ":" + port );
if ( encryption == SSL ) {
// env.put( "java.naming.ldap.factory.socket", "CustomSocketFactory" );
}
ctx = new InitialLdapContext( env, null );
if ( encryption != START_TLS )
tls = null;
else {
tls = (StartTlsResponse) ctx.extendedOperation( new StartTlsRequest() );
tls.setHostnameVerifier( hostnameVerifier );
tls.negotiate( sslContext.getSocketFactory() );
}
我们可以添加自己的CustomSocketFactory
,但是如何传递信息呢?
We could add out own CustomSocketFactory
, but how to pass information to that?
推荐答案
对于其他人有同样的问题:我为我的情况找到了一个非常丑陋的解决方案:
For others have the same problem: I found a very ugly solution for my case:
import javax.net.SocketFactory;
public abstract class ThreadLocalSocketFactory
extends SocketFactory
{
static ThreadLocal<SocketFactory> local = new ThreadLocal<SocketFactory>();
public static SocketFactory getDefault()
{
SocketFactory result = local.get();
if ( result == null )
throw new IllegalStateException();
return result;
}
public static void set( SocketFactory factory )
{
local.set( factory );
}
public static void remove()
{
local.remove();
}
}
像这样使用它:
env.put( "java.naming.ldap.factory.socket", ThreadLocalSocketFactory.class.getName() );
ThreadLocalSocketFactory.set( sslContext.getSocketFactory() );
try {
ctx = new InitialLdapContext( env, null );
} finally {
ThreadLocalSocketFactory.remove();
}
不太好,但它有效.JNDI 在这里应该更灵活...
Not nice, but it works. JNDI should be more flexible here...
这篇关于jndi LDAPS 自定义 HostnameVerifier 和 TrustManager的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:jndi LDAPS 自定义 HostnameVerifier 和 TrustManager
基础教程推荐
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 降序排序:Java Map 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01