SpringBoot整合Ldap的實(shí)現(xiàn)示例
LDAP(輕量目錄訪問(wèn)協(xié)議)是一種用于訪問(wèn)和維護(hù)分布式目錄信息服務(wù)的協(xié)議。目錄服務(wù)是一種存儲(chǔ)和檢索信息的服務(wù),通常用于存儲(chǔ)組織內(nèi)的用戶信息、組織結(jié)構(gòu)、網(wǎng)絡(luò)設(shè)備等數(shù)據(jù)。LDAP是一種輕量級(jí)的協(xié)議,設(shè)計(jì)用于在目錄中進(jìn)行查找和修改操作,而不是用于傳輸大量的數(shù)據(jù)。
以下是LDAP的一些基本概念:
目錄服務(wù)(Directory Service): 目錄服務(wù)是一種專門(mén)設(shè)計(jì)用于存儲(chǔ)和檢索信息的服務(wù)。與傳統(tǒng)數(shù)據(jù)庫(kù)不同,目錄服務(wù)更注重提供高效的讀取操作,支持快速的數(shù)據(jù)檢索。LDAP是一種協(xié)議,用于與目錄服務(wù)進(jìn)行通信。
目錄(Directory): 目錄是一種組織結(jié)構(gòu)化數(shù)據(jù)的方式,通常包含多個(gè)條目(Entry)。每個(gè)條目包含一組屬性值,用于描述特定實(shí)體(如用戶、組織單位、設(shè)備等)的信息。
條目(Entry): 條目是目錄中的基本單位,類似于數(shù)據(jù)庫(kù)中的一行記錄。每個(gè)條目都有一個(gè)唯一的標(biāo)識(shí)符,稱為DN(Distinguished Name)。
屬性(Attribute): 屬性是條目中存儲(chǔ)的信息的命名和值對(duì)。例如,一個(gè)用戶條目可能包含屬性如姓名、電子郵件地址、電話號(hào)碼等。
DN(Distinguished Name): DN是每個(gè)條目在目錄中的唯一標(biāo)識(shí)符,由一系列與目錄結(jié)構(gòu)相關(guān)的名稱組成。DN通常是一個(gè)層次結(jié)構(gòu),例如"cn=john,ou=users,dc=example,dc=com"。
LDAP協(xié)議: LDAP定義了客戶端和目錄服務(wù)器之間進(jìn)行通信的規(guī)則。它使用TCP/IP協(xié)議棧,通常在389端口上運(yùn)行。LDAP協(xié)議支持多種操作,包括搜索、添加、刪除、修改等,以便對(duì)目錄中的數(shù)據(jù)進(jìn)行操作。
LDAP被廣泛用于企業(yè)和組織中,用于集中管理用戶、組織結(jié)構(gòu)、設(shè)備等信息。它是許多身份驗(yàn)證和訪問(wèn)控制系統(tǒng)的基礎(chǔ),如單點(diǎn)登錄(SSO)系統(tǒng)。
步驟一:配置LDAP連接屬性:
在application.properties或application.yml文件中添加LDAP連接屬性,例如LDAP服務(wù)器URL、用戶名、密碼等。
步驟二:創(chuàng)建LDAP配置類:
創(chuàng)建一個(gè)@Configuration類,并使用@EnableWebSecurity注解啟用Web安全性配置。在配置類中,可以使用LDAP的相關(guān)配置屬性來(lái)配置LDAP連接和認(rèn)證提供者。
步驟三:創(chuàng)建LDAP認(rèn)證提供者:
實(shí)現(xiàn)UserDetailsService接口并重寫(xiě)其中的loadUserByUsername()方法,要在Spring Boot項(xiàng)目中整合LDAP(輕量級(jí)目錄訪問(wèn)協(xié)議),可以使用Spring LDAP模塊。以下是一個(gè)簡(jiǎn)單的示例,展示如何在Spring Boot中整合LDAP,并提供一些常見(jiàn)的操作示例。
整合步驟
1.引入POM依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-ldap</artifactId> </dependency>
2.在application.properties或application.yml文件中提供LDAP連接的配置信息
ldap.url=ldap://your-ldap-server:389 ldap.base=dc=example,dc=com ldap.userDnPattern=uid={0},ou=people ldap.userSearchBase=ou=people
3.創(chuàng)建LdapDemoConfig
package com.example.springbootidapdemo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ldap.core.LdapTemplate; import org.springframework.ldap.core.support.LdapContextSource; @Configuration public class LdapDemoConfig { @Bean public LdapTemplate ldapTemplate() { LdapContextSource contextSource = new LdapContextSource(); contextSource.setUrl("ldap://localhost:389"); contextSource.setBase("dc=example,dc=com"); contextSource.setUserDn("cn=admin,dc=example,dc=com"); contextSource.setPassword("adminpassword"); contextSource.afterPropertiesSet(); LdapTemplate ldapTemplate = new LdapTemplate(contextSource); ldapTemplate.setIgnorePartialResultException(true); ldapTemplate.setDefaultTimeLimit(1000); ldapTemplate.setDefaultCountLimit(100); return ldapTemplate; } }
4.方法概述及對(duì)應(yīng)Demo
前提
:需要提供基礎(chǔ)DN、過(guò)濾器、搜索控件和屬性映射器。實(shí)際使用時(shí),需要根據(jù)LDAP目錄的結(jié)構(gòu)和屬性進(jìn)行相應(yīng)的配置。
1.ldapTemplate.find(根據(jù)指定的搜索條件在LDAP目錄中查找條目并返回結(jié)果)
public <T> T find( String dn, String filter, SearchControls controls, AttributesMapper<T> mapper)
dn
: 搜索的基礎(chǔ)DN(Distinguished Name),表示搜索的起始位置。filter
: LDAP搜索過(guò)濾器,定義要匹配的條目的條件。controls
: 搜索控件,用于配置搜索的一些參數(shù),例如搜索范圍、返回的屬性等。mapper
: 用于將搜索結(jié)果映射為對(duì)象的 AttributesMapper。
該方法會(huì)執(zhí)行LDAP搜索并返回滿足條件的第一個(gè)條目。如果沒(méi)有匹配的條目,返回 null。
Demo如下:
@Service public class LdapService { @Autowired private LdapTemplate ldapTemplate; public User findUser(String username) { String baseDn = "ou=people,dc=example,dc=com"; String filter = "(uid=" + username + ")"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); return ldapTemplate.find(baseDn, filter, controls, new UserAttributesMapper()); } private static class UserAttributesMapper implements AttributesMapper<User> { @Override public User mapFromAttributes(Attributes attributes) throws NamingException { return new User(/* user properties */); } } }
下述demo只展示關(guān)鍵代碼塊、重復(fù)描述不再過(guò)多贅述
2.ldapTemplate.findAll(根據(jù)指定的搜索條件在LDAP目錄中查找多個(gè)條目并返回結(jié)果列表)
public <T> List<T> findAll( String base, String filter, SearchControls controls, AttributesMapper<T> mapper)
base
: 搜索的基礎(chǔ)DN(Distinguished Name),表示搜索的起始位置。
該方法會(huì)執(zhí)行LDAP搜索并返回滿足條件的所有條目的列表。如果沒(méi)有匹配的條目,返回空列表。
Demo如下:
public List<User> findAllUsers() { String baseDn = "ou=people,dc=example,dc=com"; String filter = "(objectClass=person)"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); return ldapTemplate.findAll(baseDn, filter, controls, new UserAttributesMapper()); }
3.ldapTemplate.findOne(根據(jù)指定的搜索條件在LDAP目錄中查找單個(gè)條目并返回結(jié)果)
注意
:如果沒(méi)有匹配的條目,拋出 javax.naming.NameNotFoundException
異常。如果有匹配的多個(gè)條目,拋出 javax.naming.NamingException
異常
public <T> T findOne( String dn, String filter, AttributesMapper<T> mapper)
Demo如下:
public User findUser(String username) { String baseDn = "ou=people,dc=example,dc=com"; String filter = "(uid=" + username + ")"; return ldapTemplate.findOne(baseDn, filter, new UserAttributesMapper()); }
4.ldapTemplate.findByDn(根據(jù)給定的DN(Distinguished Name)查找單個(gè)條目并返回結(jié)果)
public <T> T findByDn(String dn, AttributesMapper<T> mapper)
該方法會(huì)執(zhí)行LDAP搜索并返回指定DN的條目,如果沒(méi)有找到匹配的條目,返回 null。
Demo如下:
public User findUserByDn(String userDn) { return ldapTemplate.findByDn(userDn, new UserAttributesMapper()); }
5.ldapTemplate.findForStream(用于從 LDAP 目錄中以流的方式獲取多個(gè)條目的結(jié)果)
public <T> Stream<T> findForStream( String base, String filter, SearchControls controls, AttributesMapper<T> mapper)
ldapTemplate.findForStream
方法會(huì)執(zhí)行LDAP搜索并返回一個(gè)流(Stream),其中包含滿足條件的所有條目的結(jié)果。通過(guò)使用流的方式,可以更高效地處理大量的搜索結(jié)果,而不必一次性將所有結(jié)果加載到內(nèi)存中。
Demo如下:
public List<User> findAllUsers() { String baseDn = "ou=people,dc=example,dc=com"; String filter = "(objectClass=person)"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); Stream<User> userStream = ldapTemplate.findForStream(baseDn, filter, controls, new UserAttributesMapper()); return userStream.collect(Collectors.toList()); }
注意
:ldapTemplate.findForStream 方法是從 Spring LDAP 2.2 版本開(kāi)始引入的。確保使用的是兼容的 Spring LDAP 版本。如果版本較舊,可能需要升級(jí)到兼容的版本或者使用其他方法來(lái)處理 LDAP 搜索結(jié)果流
6.ldapTemplate.search(用于執(zhí)行靈活的LDAP搜索并返回結(jié)果)
public <T> List<T> search( String base, String filter, SearchControls controls, AttributesMapper<T> mapper)
與之前介紹的 ldapTemplate.findAll
方法相似,ldapTemplate.search
方法也執(zhí)行LDAP搜索,但它提供更多的靈活性,可以更精確地配置搜索參數(shù)。該方法返回滿足條件的所有條目的列表。
Demo如下:
public List<User> searchUsers(String filter) { String baseDn = "ou=people,dc=example,dc=com"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); return ldapTemplate.search(baseDn, filter, controls, new UserAttributesMapper()); }
7.ldapTemplate.searchForContext(用于執(zhí)行LDAP搜索并返回搜索結(jié)果的上下文(DirContext))
public DirContext searchForContext( String base, String filter, SearchControls controls)
與之前介紹的 ldapTemplate.search
方法相比ldapTemplate.searchForContext
返回的是搜索結(jié)果的上下文,而不是直接返回映射后的對(duì)象列表。這樣的設(shè)計(jì)使得可以更靈活地處理搜索結(jié)果,包括對(duì)搜索結(jié)果的進(jìn)一步處理、解析和操作。
Demo如下:
public DirContext searchForContext(String filter) { String baseDn = "ou=people,dc=example,dc=com"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); return ldapTemplate.searchForContext(baseDn, filter, controls); }
8.ldapTemplate.searchForObject(用于執(zhí)行LDAP搜索并返回單個(gè)對(duì)象作為結(jié)果)
public <T> T searchForObject( String base, String filter, SearchControls controls, Class<T> requiredType)
requiredType: 期望的返回類型。
該方法執(zhí)行LDAP搜索并返回單個(gè)對(duì)象,而不是返回一個(gè)對(duì)象列表。這可以方便地用于查找特定條件下的唯一條目。
Demo如下:
public User searchForUser(String username) { String baseDn = "ou=people,dc=example,dc=com"; String filter = "(uid=" + username + ")"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); return ldapTemplate.searchForObject(baseDn, filter, controls, User.class); }
注意
:如果沒(méi)有找到匹配的條目,ldapTemplate.searchForObject 方法將返回 null
9.ldapTemplate.searchForStream(用于執(zhí)行LDAP搜索并返回結(jié)果的流(Stream))
public <T> Stream<T> searchForStream( String base, String filter, SearchControls controls, Class<T> requiredType)
該方法執(zhí)行LDAP搜索并返回一個(gè)流(Stream),其中包含滿足條件的所有條目的結(jié)果。通過(guò)使用流的方式,可以更高效地處理大量的搜索結(jié)果,而不必一次性將所有結(jié)果加載到內(nèi)存中。
Demo如下:
public List<User> searchForUsers(String filter) { String baseDn = "ou=people,dc=example,dc=com"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); Stream<User> userStream = ldapTemplate.searchForStream(baseDn, filter, controls, User.class); return userStream.collect(Collectors.toList()); }
10.ldapTemplate.rebind(用于重新綁定(更新)LDAP目錄中的條目)
public void rebind(String dn, Object obj, Attributes attributes)
obj: 要重新綁定的對(duì)象。
該方法會(huì)將指定的對(duì)象和屬性重新綁定到LDAP目錄中的指定DN。如果指定的DN不存在,則會(huì)創(chuàng)建新的條目。如果已存在具有相同DN的條目,則會(huì)更新現(xiàn)有條目的屬性。
public void updateUserInfo(String userDn, User newUser) { // Assume User class has appropriate getters and setters for user attributes Attributes attributes = // create or update attributes based on newUser ldapTemplate.rebind(userDn, newUser, attributes); }
注意
:具體的 Attributes 對(duì)象的創(chuàng)建或更新需要根據(jù)您的數(shù)據(jù)模型和需求進(jìn)行調(diào)整
11.ldapTemplate.rename(用于重命名(移動(dòng))LDAP目錄中的條目)
public void rename(String oldDn, String newDn)
oldDn
: 要重命名的舊DN,表示LDAP目錄中的一個(gè)條目。newDn
: 新的DN,表示條目在LDAP目錄中的新位置。
該方法會(huì)將指定的條目從舊的DN移動(dòng)到新的DN,實(shí)現(xiàn)重命名的效果。
Demo如下:
public void renameUser(String oldDn, String newDn) { ldapTemplate.rename(oldDn, newDn); }
注意
:新的DN必須包含新的父級(jí)DN,以確保條目被正確移動(dòng)到新的位置。例如,如果要將用戶從 "ou=people,dc=example,dc=com"
移動(dòng)到"ou=otherPeople,dc=example,dc=com"
,則新的DN應(yīng)為"uid=john,ou=otherPeople,dc=example,dc=com"
。
12.ldapTemplate.modifyAttributes(用于修改LDAP目錄中條目的屬性值)
public void modifyAttributes(String dn, ModificationItem[] mods)
mods: 要應(yīng)用的修改項(xiàng)數(shù)組,表示要對(duì)條目進(jìn)行的修改操作。
修改項(xiàng)(ModificationItem
)由兩個(gè)屬性組成:修改操作類型(DirContext.ADD_ATTRIBUTE、DirContext.REMOVE_ATTRIBUTE
或 DirContext.REPLACE_ATTRIBUTE
)和要修改的屬性(Attribute
)。
Demo如下:
public void updateUserPassword(String userDn, String newPassword) { ModificationItem[] mods = new ModificationItem[1]; Attribute attribute = new BasicAttribute("userPassword", newPassword); mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attribute); ldapTemplate.modifyAttributes(userDn, mods); }
上述示例中,updateUserPassword
方法使用了 ldapTemplate.modifyAttributes
來(lái)根據(jù)用戶DN(userDn)修改用戶密碼。首先,創(chuàng)建一個(gè) ModificationItem
數(shù)組,包含要進(jìn)行的修改操作。在這個(gè)示例中,它只包含一項(xiàng):用新密碼替換(DirContext.REPLACE_ATTRIBUTE)userPassword
屬性。然后,將這個(gè)修改項(xiàng)數(shù)組傳遞給 ldapTemplate.modifyAttributes
方法,以便進(jìn)行修改
13.ldapTemplate.authenticate(用于對(duì)LDAP進(jìn)行認(rèn)證操作)
public boolean authenticate(String base, String filter, String password)
password: 用戶密碼,用于認(rèn)證操作。
該方法用于驗(yàn)證給定的用戶密碼是否與LDAP中指定條件的用戶匹配。如果匹配成功,則返回 true,否則返回 false。
Demo如下:
public boolean authenticateUser(String username, String password) { String baseDn = "ou=people,dc=example,dc=com"; String filter = "(uid=" + username + ")"; return ldapTemplate.authenticate(baseDn, filter, password); }
上述示例中,authenticateUser
方法使用了 ldapTemplate.authenticate
來(lái)驗(yàn)證用戶的身份。需要提供基礎(chǔ)DN、過(guò)濾器和用戶密碼。該方法將驗(yàn)證提供的用戶名和密碼是否匹配LDAP中指定條件的用戶,如果匹配成功,則返回 true,表示認(rèn)證通過(guò)。
到此這篇關(guān)于SpringBoot整合Ldap的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot整合Ldap內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringLDAP連接LDAPS證書(shū)報(bào)錯(cuò)問(wèn)題及解決
- springboot操作ldap全過(guò)程
- springboot配置ldaps連接方式
- Spring Security LDAP實(shí)現(xiàn)身份驗(yàn)證的項(xiàng)目實(shí)踐
- SpringBoot整合LDAP的流程分析
- 淺談Spring Security LDAP簡(jiǎn)介
- Vue+Jwt+SpringBoot+Ldap完成登錄認(rèn)證的示例代碼
- Spring Boot中使用LDAP來(lái)統(tǒng)一管理用戶信息的示例
- Spring Boot 連接LDAP的方法
- Spring LDAP目錄服務(wù)的使用示例
相關(guān)文章
java生成圖片驗(yàn)證碼返回base64圖片信息方式
這篇文章主要介紹了java生成圖片驗(yàn)證碼返回base64圖片信息方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Mybatis如何使用ognl表達(dá)式實(shí)現(xiàn)動(dòng)態(tài)sql
這篇文章主要介紹了Mybatis使用ognl表達(dá)式實(shí)現(xiàn)動(dòng)態(tài)sql的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06java如何實(shí)現(xiàn)postman中用x-www-form-urlencoded參數(shù)的請(qǐng)求
在Java開(kāi)發(fā)中,模擬Postman發(fā)送x-www-form-urlencoded類型的請(qǐng)求是一個(gè)常見(jiàn)需求,本文主要介紹了如何在Java中實(shí)現(xiàn)這一功能,首先,需要通過(guò)導(dǎo)入http-client包來(lái)創(chuàng)建HTTP客戶端,接著,利用該客戶端發(fā)送Post請(qǐng)求2024-09-09Java基礎(chǔ)知識(shí)之I/O流和File類文件操作
眾所周知java語(yǔ)言提供給程序員非常多的包供編程時(shí)使用,方便又快捷,下面這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)知識(shí)之I/O流和File類文件操作的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-04-04JAVA面試題 從源碼角度分析StringBuffer和StringBuilder的區(qū)別
這篇文章主要介紹了JAVA面試題 從源碼角度分析StringBuffer和StringBuilder的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面我們來(lái)一起學(xué)習(xí)下吧2019-07-07