如何在 Spring LDAP 中配置 SSL?

How to configure SSL in Spring LDAP?

我是 spring ldap 的新手,在通过 SSL 连接到 LDAP 时遇到问题。 我正在使用 Spring LDAP 2.0 连接 LDAP。

applicationContext.xml

   <context:property-placeholder location="classpath:ldap.properties" ignore-  unresolvable="true"/>

   <ldap:context-source id="contextSource" password="${ldap.password}"
        url="${ldap.url}" username="${ldap.userDn}" base="${ldap.base}" >
   </ldap:context-source>

   <ldap:ldap-template id="ldapTemplate" context-source-ref="contextSource" />


Entries from Ldap property file:

   ldap.url=ldaps://eun4p3.stp-dev.st.com:636
   ldap.userDn=CN=IP User,OU=AdminAccounts,DC=stp-dev,DC=st,DC=com
   ldap.password=useme@123
   ldap.base=OU=ST,OU=People,DC=stp-dev,DC=st,DC=com
   ldap.clean=false

我已将提供的自签名证书导入到 cacerts 文件中,使用:

   keytool -keystore cacerts -importcert -alias addevcer -file  C:\Users\kadianr\Desktop\eun4p3.cer

以下是我在调用 ldaps://url:636

时遇到的错误
Caused by: org.springframework.ldap.CommunicationException: simple bind failed: eun4p3.stp-dev.st.com:636; nested exception is javax.naming.CommunicationException: simple bind failed: eun4p3.stp-dev.st.com:636 [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
    at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:108) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:356) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:140) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.support.AbstractContextSource.getReadWriteContext(AbstractContextSource.java:175) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy.getReadWriteContext(TransactionAwareContextSourceProxy.java:88) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy.getReadOnlyContext(TransactionAwareContextSourceProxy.java:61) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:357) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:309) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:642) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:578) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.LdapTemplate.find(LdapTemplate.java:1836) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.LdapTemplate.find(LdapTemplate.java:1857) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.LdapTemplate.findOne(LdapTemplate.java:1865) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at com.st.liotroevo.web.dao.UserADRepository.findBySamAccountName(UserADRepository.java:48) [classes:]
    at com.st.liotroevo.web.service.UserService.findUserBySamAccName(UserService.java:75) [classes:]
    at com.st.liotroevo.web.service.UserService.generateSamAccount(UserService.java:145) [classes:]
    at com.st.liotroevo.web.service.UserService.populateUserBaiscADAttributes(UserService.java:101) [classes:]
    at com.st.liotroevo.web.service.serviceImpl.IPRegistrationServiceImpl.createUser(IPRegistrationServiceImpl.java:48) [classes:]
    ... 39 more
Caused by: javax.naming.CommunicationException: simple bind failed: eun4p3.stp-dev.st.com:636 [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
    at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:215) [rt.jar:1.7.0_21]
    at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2740) [rt.jar:1.7.0_21]
    at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:316) [rt.jar:1.7.0_21]
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:193) [rt.jar:1.7.0_21]
    at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:211) [rt.jar:1.7.0_21]
    at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154) [rt.jar:1.7.0_21]
    at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84) [rt.jar:1.7.0_21]
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684) [rt.jar:1.7.0_21]
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307) [rt.jar:1.7.0_21]
    at javax.naming.InitialContext.init(InitialContext.java:242) [rt.jar:1.7.0_21]
    at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:153) [rt.jar:1.7.0_21]
    at org.springframework.ldap.core.support.LdapContextSource.getDirContextInstance(LdapContextSource.java:42) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:344) [spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
    ... 55 more
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) [jsse.jar:1.7.0_21]
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1886) [jsse.jar:1.7.0_21]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276) [jsse.jar:1.7.0_21]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270) [jsse.jar:1.7.0_21]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341) [jsse.jar:1.7.0_21]
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153) [jsse.jar:1.7.0_21]
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868) [jsse.jar:1.7.0_21]
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:804) [jsse.jar:1.7.0_21]
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016) [jsse.jar:1.7.0_21]
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) [jsse.jar:1.7.0_21]
    at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:882) [jsse.jar:1.7.0_21]
    at sun.security.ssl.AppInputStream.read(AppInputStream.java:102) [jsse.jar:1.7.0_21]
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:235) [rt.jar:1.7.0_21]
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:275) [rt.jar:1.7.0_21]
    at java.io.BufferedInputStream.read(BufferedInputStream.java:334) [rt.jar:1.7.0_21]
    at com.sun.jndi.ldap.Connection.run(Connection.java:849) [rt.jar:1.7.0_21]
    ... 1 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385) [rt.jar:1.7.0_21]
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) [rt.jar:1.7.0_21]
    at sun.security.validator.Validator.validate(Validator.java:260) [rt.jar:1.7.0_21]
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) [jsse.jar:1.7.0_21]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231) [jsse.jar:1.7.0_21]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126) [jsse.jar:1.7.0_21]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1323) [jsse.jar:1.7.0_21]
    ... 12 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196) [rt.jar:1.7.0_21]
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268) [rt.jar:1.7.0_21]
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380) [rt.jar:1.7.0_21]

我已在 http://docs.spring.io/autorepo/docs/spring-ldap/2.0.3.CI-SNAPSHOT/reference/#configuration

浏览文档

我已经解决了问题。 jdk 中安装的证书存在问题。我们尝试安装由 CA 签名的不同证书并且有效。 我们只需要使用带端口 636 的 ldaps 并在 cacerts 中安装证书..就是这样。

如果您的公司有一个带有证书的内部网站,您实际上可以像这样在您的应用程序启动时创建一个信任库:

    final String KS_PASSWORD = "dummy";
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null, KS_PASSWORD.toCharArray());
    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    try (InputStream cert = new URL("http://pki.yourcompany.intranet/root.pem").openStream()) {
        Certificate certificate = cf.generateCertificate(cert);
        ks.setCertificateEntry(certificateName, certificate);
    }
    File keystore = new File("truststore.jks").getAbsoluteFile();
    try (FileOutputStream fos = new FileOutputStream(keystore)) {
        ks.store(fos, KS_PASSWORD.toCharArray());
    }
    System.setProperty("javax.net.ssl.trustStore", keystore.getAbsolutePath());
    System.setProperty("javax.net.ssl.trustStorePassword", KS_PASSWORD);

记得在 Spring 实例化 LDAP bean 之前设置 javax.* 属性。除了通过网络,您还可以将证书存储在类路径中(在您的 jar 中)并使用 Spring 的资源注入它们。