2013-07-15 76 views
4

我手里有一个SSL LDAP服务器证书。我想用它来使用UnboundID SDK连接到LDAP服务器。如何使用UnboundID SDK通过SSL服务器证书连接到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); 

请注意,CertificateTrustManager在UnboundID SDK中不存在。 怎么可能做到这一点?

回答

4

我发现该解决方案使用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 :)

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); 
3

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

如果您不知道个人证书是什么,但知道他们都有一个共同的发行人,并且您相信发行人只颁发了优质证书,那么您可以为该发行人包含信托信息。

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

+0

感谢您的回答(+1)!我找到了解决方案。很高兴听取您的意见。 – Michael

-1

虽然不建议出于安全的原因,有时可能至少进行测试的情况下使用TrustAllTrustManager有用的连接到LDAP如下:

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

这不应该用于生产环境!

相关问题