如何使用 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 服务器?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Azure.ServiceBus.Messaging C# SDK for SAS 令牌的服务总线连接字符串