如何为spring ldap提供密钥库和信任库

时间:2018-01-23 13:09:26

标签: spring ssl ldap

尝试使用spring LdapTemplate连接到ldap服务器时,我需要提供truststore和keystore。 我无法使用keytool导入认证或由系统属性javax.net.ssl.trustStore设置

现在我按以下方式配置:

   <bean id="authenticationStrategy" class="org.springframework.ldap.core.support.DefaultTlsDirContextAuthenticationStrategy">
       <property name="sslSocketFactory">
            <bean class="com.sc.cops.common.auth.ssl.SslSocketFactoryBuilder">
                <property name="trustStoreLocation" value="${oud.ldap.keyTrustLocation}" />
                <property name="trustStorePassword" value="Password1" />
              <!-- <property name="trustStorePassword">
                   <enc:decrypt key="${common.encryption.key}" cipher-text="${common.ssl.mq.keystore.password}" />
                </property> -->  
                <property name="keyStoreLocation" value="${oud.ldap.keyTrustLocation}" />
                <property name="keyStorePassword" value="Password1" />
            </bean>
        </property>
    </bean>

    <bean id="ldapContextSource"
        class="org.springframework.ldap.core.support.LdapContextSource">
        <property name="url" value="ldaps://${ldap.server}:${ldap.port}/" />
        <property name="userDn" value="${ldap.oud.userDn}" />
        <property name="password" value="${ldap.oud.password}" />
        <property name="authenticationStrategy" ref="authenticationStrategy"/>
    </bean>

    <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
        <property name="contextSource" ref="ldapContextSource" />
    </bean>

在com.sc.cops.common.auth.ssl.SslSocketFactoryBuilder中,我们创建了SSLSocketFactory:

@Override
public SSLSocketFactory getObject() throws IOException, GeneralSecurityException {

    TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    KeyStore trustStore = loadKeyStore(getTrustStoreLocation(), getTrustStoreType(), getTrustStorePassword());
    trustMgrFactory.init(trustStore);

    KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    KeyStore keyStore = loadKeyStore(getKeyStoreLocation(), getKeyStoreType(), getKeyStorePassword());
    keyMgrFactory.init(keyStore, toCharArray(getKeyStorePassword()));

    SSLContext sslContext = SSLContext.getInstance(SSL_VERSION);
    sslContext.init(keyMgrFactory.getKeyManagers(), trustMgrFactory.getTrustManagers(), null);

    return sslContext.getSocketFactory();
}

我调试代码,我可以看到密钥库和信任库正确加载。我提供的jks文件是正确的。 但是当我尝试进行身份验证时,我收到了错误

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.

1 个答案:

答案 0 :(得分:0)

我无法使其与AuthenticationStrategy类一起使用。

我们通过以下方法解决了该问题:

  • 实现自定义套接字工厂
  • 将此内容添加到ldap上下文配置中的BaseEnvironmentProperties中。
  • 使用初始化bean来保留类似于spring的配置。

实现初始化bean:

   public class SystemPropertyInitializer implements InitializingBean {
      @Value("${truststore.path}")
      private String truststorePath;

     @Value("${truststore.pass}")
     private String truststorePass;

     @Override
     public void afterPropertiesSet() throws Exception {
        System.setProperty(Utils.SOCKET_FACTORY_TSPATH, truststorePath);
        System.setProperty(Utils.SOCKET_FACTORY_TSPASS, truststorePass);
     }
  1. 设置ldap模板时:

    LdapContextSource contextSource = new LdapContextSource();
    contextSource.setUrl(getUrl());
    contextSource.setBase(getBase());
    contextSource.setUserDn(getUser());
    contextSource.setPassword(getLdapPass());
    Map<String, Object> baseEnvironmentProperties = new HashMap<String, Object>();
    baseEnvironmentProperties.put("java.naming.ldap.factory.socket", "com.custom.LdapSocketFactory");
    contextSource.setBaseEnvironmentProperties(baseEnvironmentProperties );
    contextSource.afterPropertiesSet();
    

我找不到通过插座工厂的另一种方法...即通过Autowired ...所以 套接字工厂的实现从env变量中加载了信任信息。

SSL异常发生在初始化初始上下文时。从我看到的是 在加载初始上下文之前,authenticationStrategy.setupEnvironment(env,主体,凭据) 叫做。在类AbstractTlsDirContextAuthenticationStrategy中,此方法不执行任何操作。所以工厂呢 没有在那里设置...无论如何,我认为这更多是在ldap服务器上的身份验证,即一旦握手 发生。我的意思是,它确实在类名中说了很多:-)

另请参阅:how to accept self-signed certificates for JNDI/LDAP connections?