【问题标题】:how to provide keystore and trust store to spring ldap如何为spring ldap提供密钥库和信任库
【发布时间】:2018-01-23 13:09:26
【问题描述】:

尝试使用 spring LdapTemplate 连接到 ldap 服务器时,我需要提供信任库和密钥库。 我无法使用 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.

【问题讨论】:

  • 有几种方法可以设置系统属性。你加载一个属性文件吗?
  • 我说不能通过系统属性设置,因为在我们的系统中,我们已经使用这种方式设置了另一个 jks 文件。而且我不想将这个新认证添加到现有的 jks 文件中。
  • 这里几乎每天都会被问到这个问题。要么您没有加载正确的密钥库,要么它不包含您相信的可信证书。添加 -Djavax.net.debug=all 并检查密钥库加载及其证书。将证书与服务器的证书进行比较(比较序列号)
  • @EugèneAdell 这绝对不是每天都在问的问题,而且要实现 OP 想要的也并不简单。
  • @Lezard 我询问了用户没有发布的调试日志。

标签: spring ssl ldap


【解决方案1】:

我无法让它与 AuthenticationStrategy 类一起工作。

我们通过以下方式解决了它:

  • 实现自定义套接字工厂
  • 将 this 添加到 ldap 上下文配置中的 BaseEnvironmentProperties。
  • 使用初始化 bean 以允许坚持类似弹簧的配置。

实现一个初始化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...所以 套接字工厂的实现从环境变量中加载了信任信息。

在初始化初始上下文时发生 SSL 异常。从我可以看到的是 在加载初始上下文之前 authenticationStrategy.setupEnvironment(env, principal, credentials) 叫做。在类 AbstractTlsDirContextAuthenticationStrategy 中,此方法什么也不做。所以工厂做 不要在那里设置...无论如何,我认为这更像是 ldap 服务器上的身份验证,即一旦握手 发生了。我的意思是,它确实在类名中说明了很多内容:-)

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

【讨论】:

    猜你喜欢
    • 2018-05-06
    • 2019-11-28
    • 2010-09-24
    • 2018-11-11
    • 1970-01-01
    • 2015-12-02
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    相关资源
    最近更新 更多