在 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。在此 ContextSource
中 binary
属性 不存在。
这就是我的问题的原因,属性 没有设置。
无法通过 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();
}
}
我希望有人能帮我解决 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。在此 ContextSource
中 binary
属性 不存在。
这就是我的问题的原因,属性 没有设置。
无法通过 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();
}
}