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
- 将log4j 1.2配置转换为log4j 2配置 2022-01-01
- C++ 和 Java 进程之间的共享内存 2022-01-01
- Spring Boot连接到使用仲裁器运行的MongoDB副本集 2022-01-01
- value & 是什么意思?0xff 在 Java 中做什么? 2022-01-01
- Eclipse 插件更新错误日志在哪里? 2022-01-01
- 如何使用WebFilter实现授权头检查 2022-01-01
- Java包名称中单词分隔符的约定是什么? 2022-01-01
- Jersey REST 客户端:发布多部分数据 2022-01-01
- Safepoint+stats 日志,输出 JDK12 中没有 vmop 操作 2022-01-01
- 从 finally 块返回时 Java 的奇怪行为 2022-01-01