如何使用 UnboundID SDK 连接带有 SSL 服务器证书的 LDAP 服务器?

Posted

技术标签:

【中文标题】如何使用 UnboundID SDK 连接带有 SSL 服务器证书的 LDAP 服务器?【英文标题】:How to use UnboundID SDK to connect to an LDAP server with the SSL server certificate? 【发布时间】:2013-07-13 10:40:07 【问题描述】:

我手里有一个 SSL LDAP 服务器证书。我想用它来使用 UnboundID SDK 连接到 LDAP 服务器。

我不想像这里显示的那样使用 com.unboundid.util.ssl.TrustAllTrustManager: Using UnboundID SDK with an SSL certificate file to connect to LDAP server in android app

以下 TrustManager 不符合我们的产品要求:

com.unboundid.util.ssl.PromptTrustManager
com.unboundid.util.ssl.HostNameTrustManager
com.unboundid.util.ssl.ValidityDateTrustManager

我不希望任何用户交互,以及我在验证证书颁发者的 TrustManager 上方的列表中遗漏的内容。

另外,我不想在任何密钥库中插入 LDAP 服务器证书,所以我不能使用以下 信任管理器:

com.unboundid.util.ssl.WrapperKeyManager
com.unboundid.util.ssl.PKCS11KeyManager
com.unboundid.util.ssl.KeyStoreKeyManager

我想做如下代码:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(byteArrayInputStream);
SSLUtil sslUtil = new SSLUtil(new CertificateTrustManager(cert));
SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
LDAPConnection connection = new LDAPConnection(socketFactory,
     "server.example.com", 636);

请注意,UnboundID SDK 中不存在 CertificateTrustManager。 怎么可能呢?

【问题讨论】:

【参考方案1】:

我使用Using UnboundID SDK with an SSL certificate file to connect to LDAP server in Android app 和How to import a .cer certificate into a java keystore?(Patrick M 的回答)找到了解决方案。

现在我可以从 UI 获取证书并通过 SSL 连接到 LDAP :)

import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.util.ssl.SSLUtil;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

String base64EncodedCertificateString = "...";
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(base64EncodedCertificateString.getBytes());
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
int i = 0;
while (byteArrayInputStream.available() > 0) 
    Certificate cert = cf.generateCertificate(byteArrayInputStream);
    trustStore.setCertificateEntry("cert " + i++, cert);


TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();
SSLUtil sslUtil = new SSLUtil(trustManagers);
SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
LDAPConnection connection = new LDAPConnection(socketFactory);
connection.connect("place.myserver.com", 636);

【讨论】:

【参考方案2】:

如果有一个特定的证书或一组您想要信任的证书,那么您可以创建自己的自定义 javax.net.ssl.X509TrustManager 实现来检查提供的证书链并确定它是否代表预期的证书之一.您可以将有关这些证书的信息硬编码到您的代码中(或者更好的是,将其放在一个配置文件中,这样您就可以在不更改任何代码的情况下更改它)并执行诸如比较证书指纹之类的操作,以获得适当程度的保证。实际上是合法的证书。

如果您不知道各个证书是什么,但知道它们都有一个共同的颁发者,并且您相信该颁发者只会颁发好的证书,那么您可以包含该颁发者的信任信息。

如果您想允许一系列未知证书,可能来自不受信任的颁发者(并且您事先不知道这些颁发者可能是什么),并且您不想提示用户是否信任它们(你可能会缓存,所以你只需要问一次),那么我不确定你能做什么。除非您能找到某种方法来区分证书与好服务器和坏服务器,否则您的应用程序将面临信任坏证书或不信任好证书的风险。

【讨论】:

感谢您的回答 (+1)!我找到了解决方案。会为您的 cmets 感到高兴。【参考方案3】:

虽然出于安全原因不建议这样做,但有时至少在测试情况下使用 TrustAllTrustManager 很有用,如下所示:

TrustAllTrustManager tm = new TrustAllTrustManager();
TrustManager[] trustManagers = new TrustManager[] tm;
SSLUtil sslUtil = new SSLUtil(trustManagers);
SSLSocketFactory socketFactory = sslUtil.createSSLSocketFactory();
LDAPConnection connection = new LDAPConnection(socketFactory);

这不应该用于生产环境!

【讨论】:

以上是关于如何使用 UnboundID SDK 连接带有 SSL 服务器证书的 LDAP 服务器?的主要内容,如果未能解决你的问题,请参考以下文章

Unboundid 未返回请求的 LDAP 属性。为啥?

使用带有C#的Harmon.ie SDK

Firebase iOS SDK - 计算连接用户

使用 Azure.ServiceBus.Messaging C# SDK for SAS 令牌的服务总线连接字符串

如何使用 Java prometheus sdk 创建带有标签的 Gauge 度量?

您如何使用带有 Photon 实时 Javascript SDK 的安全 websocket?