一键导入
spring-ldap-integration
Подключение Spring Boot к Active Directory через LdapTemplate — зависимости, конфигурация, поиск, SearchControls для бинарных атрибутов
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Подключение Spring Boot к Active Directory через LdapTemplate — зависимости, конфигурация, поиск, SearchControls для бинарных атрибутов
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | spring-ldap-integration |
| description | Подключение Spring Boot к Active Directory через LdapTemplate — зависимости, конфигурация, поиск, SearchControls для бинарных атрибутов |
| source | auto-skill |
| extracted_at | 2026-06-11T12:55:34.865Z |
Подключение к MS AD через spring-boot-starter-data-ldap. LdapTemplate используется напрямую (не через Spring Data LDAP-репозитории).
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
spring.ldap.urls=ldap://${ldap.host} # или ldaps://host:636
spring.ldap.base=${ldap.base} # OU=ФЦПСР,DC=internal,DC=fcpsr,DC=ru
spring.ldap.username=${ldap.bind.dn} # CN=svc-user,OU=Service Accounts,DC=...
spring.ldap.password=${ldap.bind.pass}
spring.data.ldap.repositories.enabled=false # отключить Spring Data LDAP-репозитории
Важно: spring.data.ldap.repositories.enabled=false — если в проекте есть R2DBC, иначе конфликт (см. skill ldap-r2dbc-repository-conflict).
private final LdapTemplate ldapTemplate; // Spring инжектит автоматически
@Value("${spring.ldap.base}")
private String baseDn;
// Простой поиск
List<Map<String, Object>> result = ldapTemplate.search(
baseDn, // откуда ищем
"(&(objectClass=user)(mail=*))", // LDAP-фильтр
(Attributes attrs) -> { // AttributesMapper (лямбда)
Map<String, Object> map = new LinkedHashMap<>();
map.put("cn", safeGetAttr(attrs, "cn"));
return map;
}
);
| Оператор | Описание | Пример |
|---|---|---|
& | AND | (&(a=1)(b=2)) |
| | OR | (|(a=1)(b=2)) |
! | NOT | (!(a=1)) |
* | Wildcard | cn=*иван* |
:1.2.840...:=2 | Битовая маска | userAccountControl:1.2.840.113556.1.4.803:=2 (DISABLED) |
По умолчанию LDAP не возвращает некоторые атрибуты (например objectGUID). Нужно явно запросить:
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(new String[]{"*", "objectGUID"}); // "*" = все стандартные
return ldapTemplate.search(baseDn, filter, controls, mapper);
objectGUID — 16-байтный бинарный GUID, не меняется никогда. AD хранит его в mixed-endian.
Практический опыт: в JNDI (через Spring LdapTemplate) objectGUID возвращается как String с бинарными данными, а не byte[]. Конвертация через ISO_8859_1 теряет байты (замена на ?). Суффикс ;binary решает проблему нестабильно. Вывод: использовать mail как ключ синхронизации вместо objectGUID.
String filter = "(&(objectCategory=person)(mail=*)(telephoneNumber=*)"
+ "(|(&(objectClass=user)(givenName=*)(sn=*)"
+ "(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
+ "(objectClass=contact)))";
Ключевое: mail=* и telephoneNumber=* — обязательные поля (отсекаем служебные учётки). !(userAccountControl:=2) — исключаем отключенные.
private String safeGetAttr(Attributes attrs, String name) {
try {
Attribute attr = attrs.get(name);
return attr != null ? String.valueOf(attr.get(0)) : "";
} catch (Exception e) { return ""; }
}
spring.ldap.urls=ldap://dc1.domain.ru ldap://dc2.domain.ru
Spring LDAP автоматически пробует следующий сервер при ошибке подключения.
Attribute attr = attrs.get("memberOf");
NamingEnumeration<?> en = attr.getAll();
while (en.hasMore()) list.add(String.valueOf(en.next()));
Динамический LdapTemplate из БД + шифрование пароля + отключение авто-LDAP для безопасного старта без AD
Экспорт Excel с фильтром по датам — использование Thymeleaf inline для передачи дат из формы в JS
Полный цикл синхронизации справочника из Active Directory — сброс структуры, сохранение порядка, блокирующий код в WebFlux
Feature-флаг в БД (app_settings) с UI-тумблером на странице профиля
Парсинг Distinguished Name из Active Directory, извлечение OU-цепочки, правила маппинга на Department/Division и блокирующие вызовы в WebFlux
Разрешение конфликта Spring Data LDAP + R2DBC — strict mode, @Table на все entity, отключение LDAP-репозиториев