1. 概述
LDAP 目錄服務器是優化後的層次化數據存儲。通常,它們被用於存儲用於用户身份驗證和授權的用户相關信息。
在本文中,我們將探索 Spring LDAP API 以進行用户身份驗證和搜索,以及在目錄服務器中創建和修改用户。相同的 API 組可用於管理 LDAP 中的任何其他類型的條目。
2. Maven 依賴
讓我們首先添加所需的 Maven 依賴項:
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<version>3.1.2</version>
</dependency>此依賴項的最新版本可以在 https://mvnrepository.com/artifact/org.springframework.ldap/spring-ldap-core 找到。
3. 數據準備
為了本文的目的,我們首先創建以下 LDAP 條目:
ou=users,dc=example,dc=com (objectClass=organizationalUnit)在以下節點下,我們將創建新用户、修改現有用户、驗證現有用户以及搜索信息。
4. Spring LDAP APIs
Spring LDAP APIs 提供了一種方便的方式來使用各種 LDAP 目錄服務,例如 Active Directory、OpenLDAP 和其他基於 LDAP 的目錄。它允許你在 Spring 應用程序中使用 LDAP 進行身份驗證、用户管理和數據訪問。
主要功能:
- 與 LDAP 目錄的連接: 提供與各種 LDAP 目錄的連接,支持多種 LDAP 協議(如 LDAPv3)。
- 對象模型: 提供了一個基於 Java 的對象模型,用於表示 LDAP 目錄中的對象,例如用户、組和屬性。
- 查詢和搜索: 支持使用 LDAP 查詢語言進行搜索和過濾。
- 操作: 提供操作 LDAP 目錄的 API,例如添加、修改、刪除對象。
- 與 Spring 框架的集成: 與 Spring 的其他模塊(如 Spring Security)無縫集成,方便在 Spring 應用程序中使用 LDAP。
示例代碼:
// Java 代碼示例 - 檢索用户
import org.springframework.ldap.core.support.DefaultLdapConnectionFactory;
import org.springframework.ldap.core.NamedNodeDefinition;
import org.springframework.ldap.core.support.SimpleLdapConnectionFactory;
// ...
SimpleLdapConnectionFactory connectionFactory = new SimpleLdapConnectionFactory("ldap://localhost:1389"); // 替換為你的 LDAP 服務器地址
// 檢索名為 "user1" 的用户
User user = connectionFactory.getConnection().lookup("cn=user1,dc=example,dc=com");
if (user != null) {
System.out.println("User found: " + user.getName());
} else {
System.out.println("User not found.");
}
4.1. <em>ContextSource</em> & <em>LdapTemplate</em> Bean 定義
<em>ContextSource</em> 用於創建LdapTemplate。我們在下一部分將看到ContextSource在用户身份驗證中的使用:
@Bean
public LdapContextSource contextSource() {
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(env.getRequiredProperty("ldap.urls"));
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. 使用 Spring Boot
當我們在 Spring Boot 項目中工作時,可以使用 Spring Boot Starter Data Ldap 依賴項,它將自動為 LdapContextSource 和 LdapTemplate 進行儀器化。
為了啓用自動配置,我們需要確保我們已將 spring-boot-starter-data-ldap Starter 或 spring-ldap-core 定義為 pom.xml 中的依賴項:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>要連接到 LDAP,我們需要在應用程序的 application.properties 文件中提供連接設置:
spring.ldap.urls=ldap://localhost:18889
spring.ldap.base=dc=example,dc=com
spring.ldap.username=uid=admin,ou=system
spring.ldap.password=secret然後,我們將所有配置好的 LdapTemplate 注入到所需的 Service 類中。
@Autowired
private LdapTemplate ldapTemplate;4.3. 用户身份驗證
現在,讓我們實現一段簡單的邏輯來驗證現有用户:
public void authenticate(String username, String password) {
contextSource
.getContext(
"cn=" +
username +
",ou=users," +
env.getRequiredProperty("ldap.partitionSuffix"), password);
}<h3><strong>4.4. 用户創建</strong></h3>
<p>接下來,我們將創建一個新用户並將其密碼的 SHA 哈希值存儲在 LDAP 中。</p>
<p>在身份驗證過程中,LDAP 服務器會生成提供的密碼的 SHA 哈希值,並將其與存儲的哈希值進行比較。</p>
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() 是一個自定義方法,它返回提供的密碼的 SHA 哈希值的 Base64 編碼字符串。
最後,LdapTemplate 的 bind() 方法用於在 LDAP 服務器上創建條目。
4.5. 用户修改
我們可以使用以下方法修改現有用户或條目:
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.6. 用户搜索
我們可以使用搜索過濾器搜索現有用户:
public List<String> search(String username) {
return ldapTemplate
.search(
"ou=users",
"cn=" + username,
(AttributesMapper<String>) attrs -> (String) attrs.get("cn").get());
}AttributesMapper 用於從找到的條目中獲取所需的屬性值。內部而言,Spring 的 LdapTemplate 會調用 AttributesMapper 對所有找到的條目進行操作,並創建一個包含屬性值的列表。
5. 測試
<em>spring-ldap-test</em> 提供了一個基於 ApacheDS 1.5.5 的嵌入式 LDAP 服務器。為了配置嵌入式 LDAP 服務器用於測試,我們需要配置以下 Spring Bean:
@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<String> users = ldapClient
.search(SEARCH_STRING);
assertThat(users, Matchers.containsInAnyOrder(USER2, USER3));
}6. 結論
在本文中,我們介紹了 Spring LDAP API 及其在 LDAP 服務器上進行用户身份驗證、用户搜索、用户創建和修改的簡單方法。