在 Spring 嵌入式 LDAP 中存储二进制项

Store Binary Items in Spring Embedded LDAP

我希望有人能帮我解决 Spring 嵌入式 LDAP 的问题。 我使用嵌入式 LDAP 在单元测试中模拟高效的 Active Directory,但出现问题。

LDAP 设置正确(启动)并且预填充了 schema.ldif

问题来了:

在 Active Directory 中,用户的二进制属性将通过 LdapTemplate 在表示 class 的用户中读取为 byte[]。在 Active Directory 中一切正常。但是在 Spring 嵌入式 LDAP 中,该字段始终是一个字符串,当我尝试读取它时,我得到一个 ConversionException

有什么方法可以在 LDIF(或其他地方)中告诉 Spring 这个属性是二进制属性,以便将值存储为 byte[] 或将字符串作为 byte[ ] ?

我尝试将其添加为带有 :: 符号的 Base64 编码字符串,以及带有 :< 符号的文件。但两种方式都将其作为字符串存储在 LDAP 中。

我已经自己解决了这个问题。如果有人再次遇到同样的问题,这是我的解决方案:

问题不是属性存储为字符串,而是使用嵌入式 LDAP 时配置错误的客户端环境。

在客户端中,您通过 application.properties 设置环境 属性,如下所示: spring.ldap.base-environment.java.naming.ldap.attributes.binary=propertyName.

当初始化 ldap 客户端的 ContextSource 时,这个 属性 将被放入上下文中,并且属性将被解析为二进制。

但是client的ContextSource注解为ConditionalOnMissingBean。因此,如果 ContextSource 的 bean 已经存在,则不会再次初始化该 bean。

如果您使用的是嵌入式 LDAP,它会在客户端之前创建自己的 ContextSource,以便客户端使用与服务器相同的 ContextSource。在此 ContextSourcebinary 属性 不存在。

这就是我的问题的原因,属性 没有设置。

无法通过 application.properties.

将 属性 设置为环境 属性

我的解决方案是 ApplicationListener,它在初始化后将 属性 设置为源。

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.ldap.core.support.AbstractContextSource;
import org.springframework.stereotype.Component;

import java.util.Collections;

/**
 * This optimizer is necessary because the property cannot be set otherwise.
 * The LDAP Client initialises it`s ContextSource (with the property from the application.properties) on ConditionalOnMissingBean.
 * By using the embedded LDAP the bean is no longer missing and the ContextSource from the embedded LDAP is used.
 * This bean does not use any properties for the environment.
 * So we are using this optimizer to set the properties afterwards.
 */
@Component
public class LdapContextSourceOptimizer implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        AbstractContextSource contextSource = contextRefreshedEvent.getApplicationContext().getBean(AbstractContextSource.class);
        contextSource.setBaseEnvironmentProperties(Collections.singletonMap("java.naming.ldap.attributes.binary", "objectGUID"));
        contextSource.afterPropertiesSet();
    }
}