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

时间:2013-07-15 14:15:18

标签: ssl ldap ssl-certificate ldapconnection unboundid-ldap-sdk

我手中有一个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

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

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

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

另外,我不想在任何密钥库中插入LDAP服务器证书,因此我不能使用以下内容 TrustManagers:

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。 怎么可能这样做?

3 个答案:

答案 0 :(得分:6)

我使用Using UnboundID SDK with an SSL certificate file to connect to LDAP server in Android appHow 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);

答案 1 :(得分:3)

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

如果你不知道个人证书是什么,但知道他们都有一个共同的发行人,并且你相信发行人只能发行好的证书,那么你可以包括该发行人的信任信息。

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

答案 2 :(得分:0)

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

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

这不应该用于生产环境!