Spring LDAP Обзор
1. обзор
Серверы каталогов LDAP являются оптимизированными для чтения иерархическими хранилищами данных. Обычно они используются для хранения связанной с пользователем информации, необходимой для аутентификации и авторизации пользователей.
В этой статье мы рассмотрим API-интерфейсы Spring LDAP для аутентификации и поиска пользователей, а также для создания и изменения пользователей на сервере каталогов. Тот же набор API можно использовать для управления записями любого другого типа в LDAP.
2. Maven Зависимости
Начнем с добавления необходимой зависимости Maven:
org.springframework.ldap
spring-ldap-core
2.3.1.RELEASE
Последнюю версию этой зависимости можно найти по адресуspring-ldap-core.
3. Подготовка данных
Для целей этой статьи давайте сначала создадим следующую запись LDAP:
ou=users,dc=example,dc=com (objectClass=organizationalUnit)
Под этим узлом мы будем создавать новых пользователей, изменять существующих пользователей, проверять подлинность существующих пользователей и искать информацию.
4. API Spring LDAP
4.1. ContextSource &LdapTemplate Определение компонента
ContextSource используется для созданияLdapTemplate. Мы увидим использованиеContextSource во время аутентификации пользователя в следующем разделе:
@Bean
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(env.getRequiredProperty("ldap.url"));
contextSource.setBase(
env.getRequiredProperty("ldap.partitionSuffix"));
contextSource.setUserDn(
env.getRequiredProperty("ldap.principal"));
contextSource.setPassword(
env.getRequiredProperty("ldap.password"));
return contextSource;
}
LdapTemplate используется для создания и изменения записей LDAP:
@Bean
public LdapTemplate ldapTemplate() {
return new LdapTemplate(contextSource());
}
4.2. Аутентификация пользователя
Давайте теперь реализуем простую часть логики для аутентификации существующего пользователя:
public void authenticate(String username, String password) {
contextSource
.getContext(
"cn=" +
username +
",ou=users," +
env.getRequiredProperty("ldap.partitionSuffix"), password);
}
4.3. Создание пользователя
Затем давайте создадим нового пользователя и сохраним SHA-хэш пароля в LDAP.
Во время аутентификации сервер LDAP генерирует хэш SHA предоставленного пароля и сравнивает его с сохраненным:
public void create(String username, String password) {
Name dn = LdapNameBuilder
.newInstance()
.add("ou", "users")
.add("cn", username)
.build();
DirContextAdapter context = new DirContextAdapter(dn);
context.setAttributeValues(
"objectclass",
new String[]
{ "top",
"person",
"organizationalPerson",
"inetOrgPerson" });
context.setAttributeValue("cn", username);
context.setAttributeValue("sn", username);
context.setAttributeValue
("userPassword", digestSHA(password));
ldapTemplate.bind(context);
}
digestSHA() - это специальный метод, который возвращает закодированную в Base64 строку хэша SHA предоставленного пароля.
Наконец, методbind()LdapTemplate используется для создания записи на сервере LDAP.
4.4. Модификация пользователя
Мы можем изменить существующего пользователя или запись следующим способом:
public void modify(String username, String password) {
Name dn = LdapNameBuilder.newInstance()
.add("ou", "users")
.add("cn", username)
.build();
DirContextOperations context
= ldapTemplate.lookupContext(dn);
context.setAttributeValues
("objectclass",
new String[]
{ "top",
"person",
"organizationalPerson",
"inetOrgPerson" });
context.setAttributeValue("cn", username);
context.setAttributeValue("sn", username);
context.setAttributeValue("userPassword",
digestSHA(password));
ldapTemplate.modifyAttributes(context);
}
МетодlookupContext() используется для поиска указанного пользователя.
4.5. Поиск пользователей
Мы можем искать существующих пользователей, используя поисковые фильтры:
public List search(String username) {
return ldapTemplate
.search(
"ou=users",
"cn=" + username,
(AttributesMapper) attrs -> (String) attrs.get("cn").get());
}
AttributesMapper используется для получения желаемого значения атрибута из найденных записей. Внутри SpringLdapTemplate вызываетAttributesMapper для всех найденных записей и создает список значений атрибутов.
5. тестирование
spring-ldap-test предоставляет встроенный LDAP-сервер на основе ApacheDS 1.5.5. Чтобы настроить встроенный сервер LDAP для тестирования, нам нужно настроить следующий bean-компонент Spring:
@Bean
public TestContextSourceFactoryBean testContextSource() {
TestContextSourceFactoryBean contextSource
= new TestContextSourceFactoryBean();
contextSource.setDefaultPartitionName(
env.getRequiredProperty("ldap.partition"));
contextSource.setDefaultPartitionSuffix(
env.getRequiredProperty("ldap.partitionSuffix"));
contextSource.setPrincipal(
env.getRequiredProperty("ldap.principal"));
contextSource.setPassword(
env.getRequiredProperty("ldap.password"));
contextSource.setLdifFile(
resourceLoader.getResource(
env.getRequiredProperty("ldap.ldiffile")));
contextSource.setPort(
Integer.valueOf(
env.getRequiredProperty("ldap.port")));
return contextSource;
}
Давайте протестируем наш метод поиска пользователей с помощью JUnit:
@Test
public void
givenLdapClient_whenCorrectSearchFilter_thenEntriesReturned() {
List users = ldapClient
.search(SEARCH_STRING);
assertThat(users, Matchers.containsInAnyOrder(USER2, USER3));
}
6. Заключение
В этой статье мы представили Spring LDAP API и разработали простые методы для аутентификации пользователей, поиска пользователей, создания и модификации пользователей на сервере LDAP.
Как всегда, полный исходный код доступен вthis Github project. Тесты создаются в профиле Maven «live» и, следовательно, могут быть запущены с помощью опции «-P live».