当前位置: 首页 > article >正文

SpringBoot 3.x 实战:用LdapTemplate搞定用户认证与增删改查(附完整代码)

SpringBoot 3.x企业级LDAP集成实战从认证到用户管理的完整解决方案在企业级应用开发中统一身份认证是每个系统都需要解决的基础问题。LDAP作为轻量级目录访问协议因其高效的查询性能和标准化的数据结构成为众多企业用户管理的首选方案。本文将带你深入SpringBoot 3.x与Spring Data LDAP的整合实践从零构建一个完整的用户管理微服务模块。1. 环境准备与基础配置1.1 项目初始化与依赖配置首先创建一个SpringBoot 3.x项目在pom.xml中添加必要依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-ldap/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency /dependencies在application.yml中配置LDAP连接参数spring: ldap: urls: ldap://localhost:389 base: dcexample,dccom username: cnadmin,dcexample,dccom password: adminpassword pool: enabled: true max-active: 10 max-idle: 5 min-idle: 2 max-wait: 300001.2 LDAP上下文配置创建自定义配置类增强LDAP连接控制Configuration public class LdapConfig { Bean public LdapContextSource contextSource() { LdapContextSource contextSource new LdapContextSource(); contextSource.setUrl(env.getProperty(spring.ldap.urls)); contextSource.setBase(env.getProperty(spring.ldap.base)); contextSource.setUserDn(env.getProperty(spring.ldap.username)); contextSource.setPassword(env.getProperty(spring.ldap.password)); contextSource.setPooled(true); contextSource.afterPropertiesSet(); return contextSource; } Bean public LdapTemplate ldapTemplate() { LdapTemplate template new LdapTemplate(contextSource()); template.setIgnorePartialResultException(true); template.setDefaultTimeLimit(3000); template.setDefaultCountLimit(200); return template; } }2. 核心功能实现2.1 用户认证模块实现基于LDAP的身份认证服务Service public class LdapAuthService { Autowired private LdapTemplate ldapTemplate; public boolean authenticate(String username, String password) { String baseDn ouusers, ldapTemplate.getContextSource().getBaseLdapPath(); String filter ((objectClassperson)(uid{0})); return ldapTemplate.authenticate(baseDn, filter, new String[]{username}, password); } public UserDetails loadUserByUsername(String username) { String baseDn ouusers, ldapTemplate.getContextSource().getBaseLdapPath(); String filter ((objectClassperson)(uid{0})); return ldapTemplate.searchForObject( baseDn, filter, new String[]{username}, (ctx) - { Attributes attributes ctx.getAttributes(); return User.builder() .username(attributes.get(uid).get().toString()) .password() .authorities(extractRoles(attributes)) .build(); }); } private Collection? extends GrantedAuthority extractRoles(Attributes attributes) { // 角色提取逻辑 } }2.2 用户CRUD操作实现完整的用户管理功能Service public class LdapUserService { Autowired private LdapTemplate ldapTemplate; public User createUser(UserDto userDto) { Name dn LdapNameBuilder.newInstance() .add(ou, users) .add(uid, userDto.getUsername()) .build(); DirContextAdapter context new DirContextAdapter(dn); context.setAttributeValues(objectClass, new String[]{top, person, organizationalPerson, inetOrgPerson}); context.setAttributeValue(cn, userDto.getFullName()); context.setAttributeValue(sn, userDto.getLastName()); context.setAttributeValue(userPassword, userDto.getPassword()); ldapTemplate.bind(context); return findUser(userDto.getUsername()); } public User findUser(String username) { String baseDn ouusers, ldapTemplate.getContextSource().getBaseLdapPath(); String filter ((objectClassperson)(uid{0})); return ldapTemplate.searchForObject( baseDn, filter, new String[]{username}, new UserAttributesMapper()); } public void updateUser(String username, UserDto userDto) { Name dn LdapNameBuilder.newInstance() .add(ou, users) .add(uid, username) .build(); ModificationItem[] mods { new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(cn, userDto.getFullName())), new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute(sn, userDto.getLastName())) }; ldapTemplate.modifyAttributes(dn, mods); } public void deleteUser(String username) { Name dn LdapNameBuilder.newInstance() .add(ou, users) .add(uid, username) .build(); ldapTemplate.unbind(dn); } private static class UserAttributesMapper implements AttributesMapperUser { Override public User mapFromAttributes(Attributes attributes) throws NamingException { User user new User(); user.setUsername(attributes.get(uid).get().toString()); user.setFullName(attributes.get(cn).get().toString()); user.setLastName(attributes.get(sn).get().toString()); return user; } } }3. 高级功能与性能优化3.1 批量操作与分页查询处理大量用户数据时的优化策略public PageUser findAllUsers(int page, int size) { String baseDn ouusers, ldapTemplate.getContextSource().getBaseLdapPath(); String filter (objectClassperson); SearchControls controls new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); controls.setCountLimit(size); controls.setTimeLimit(3000); return ldapTemplate.searchForStream(baseDn, filter, controls, new UserAttributesMapper()) .skip(page * size) .limit(size) .collect(Collectors.collectingAndThen( Collectors.toList(), list - new PageImpl(list, PageRequest.of(page, size), countAllUsers()) )); } private long countAllUsers() { String baseDn ouusers, ldapTemplate.getContextSource().getBaseLdapPath(); String filter (objectClassperson); SearchControls controls new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); controls.setReturningAttributes(new String[]{1.1}); // 只返回数量 return ldapTemplate.search(baseDn, filter, controls, (AttributesMapperLong) attrs - 1L) .stream() .count(); }3.2 连接池与超时优化针对高并发场景的配置调整Configuration public class LdapPoolConfig { Bean public PoolConfig poolConfig() { PoolConfig config new PoolConfig(); config.setMaxTotal(20); config.setMaxIdle(10); config.setMinIdle(5); config.setMaxWait(Duration.ofSeconds(30)); config.setTestOnBorrow(true); config.setTestWhileIdle(true); return config; } Bean public LdapContextSource contextSource(PoolConfig poolConfig) { LdapContextSource contextSource new LdapContextSource(); // ...其他配置 contextSource.setPooled(true); contextSource.setPoolConfig(poolConfig); return contextSource; } }4. 安全增强与异常处理4.1 安全防护措施Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth - auth .requestMatchers(/api/public/**).permitAll() .anyRequest().authenticated() ) .sessionManagement(session - session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .addFilterBefore( new LdapAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class) .exceptionHandling(ex - ex .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)) ); return http.build(); } Bean public AuthenticationManager authenticationManager() { return new LdapAuthenticationProvider( contextSource(), ouusers, contextSource().getBaseLdapPath()); } }4.2 异常统一处理RestControllerAdvice public class LdapExceptionHandler { ExceptionHandler(InvalidNameException.class) public ResponseEntityErrorResponse handleInvalidName(InvalidNameException ex) { return ResponseEntity.badRequest() .body(new ErrorResponse(INVALID_DN_FORMAT, Invalid distinguished name format)); } ExceptionHandler(SizeLimitExceededException.class) public ResponseEntityErrorResponse handleSizeLimit(SizeLimitExceededException ex) { return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE) .body(new ErrorResponse(RESULT_SIZE_EXCEEDED, Query result exceeds size limit)); } ExceptionHandler(TimeLimitExceededException.class) public ResponseEntityErrorResponse handleTimeLimit(TimeLimitExceededException ex) { return ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT) .body(new ErrorResponse(QUERY_TIMEOUT, LDAP query timed out)); } }5. 测试与验证5.1 单元测试示例SpringBootTest public class LdapUserServiceTest { Autowired private LdapUserService userService; Test public void testCreateAndFindUser() { UserDto userDto new UserDto(); userDto.setUsername(testuser); userDto.setPassword(Test123); userDto.setFullName(Test User); userDto.setLastName(User); User created userService.createUser(userDto); assertNotNull(created); User found userService.findUser(testuser); assertEquals(Test User, found.getFullName()); } Test public void testAuthentication() { assertTrue(authService.authenticate(existinguser, correctpassword)); assertFalse(authService.authenticate(nonexistent, wrongpassword)); } }5.2 集成测试配置TestConfiguration public class TestLdapConfig { Bean Primary public LdapContextSource testContextSource() { LdapContextSource contextSource new LdapContextSource(); contextSource.setUrl(ldap://localhost:10389); contextSource.setBase(dctest,dccom); contextSource.setUserDn(uidadmin,ousystem); contextSource.setPassword(secret); contextSource.afterPropertiesSet(); return contextSource; } Bean Primary public LdapTemplate testLdapTemplate() { return new LdapTemplate(testContextSource()); } }

相关文章:

SpringBoot 3.x 实战:用LdapTemplate搞定用户认证与增删改查(附完整代码)

SpringBoot 3.x企业级LDAP集成实战:从认证到用户管理的完整解决方案 在企业级应用开发中,统一身份认证是每个系统都需要解决的基础问题。LDAP作为轻量级目录访问协议,因其高效的查询性能和标准化的数据结构,成为众多企业用户管理的…...

LSBible SDK:结构化圣经数据获取与AI集成的开发实践

1. 项目概述:为AI圣经研究打造的多语言SDK如果你正在开发与圣经内容相关的应用,无论是个人灵修工具、教会管理软件,还是想将经文无缝集成到AI助手(比如Claude、Cursor)中,你大概率会遇到一个头疼的问题&…...

Python开发与数据科学的完美结合

在当今这个数据驱动的时代,Python 作为一门强大而灵活的编程语言,已经成为了开发与数据科学领域不可或缺的工具。其简洁的语法、丰富的库支持以及强大的社区生态,使得 Python 不仅在软件开发中大放异彩,更在数据科学的各个层面发挥…...

Cursor AI编辑器版本管理实战:从下载到配置的完整指南

1. Cursor AI 编辑器:为什么你需要一个版本管理仓库 如果你是一名开发者,尤其是深度依赖 AI 辅助编程的开发者,那么 Cursor 这个名字对你来说一定不陌生。它被许多人誉为“AI 代码编辑器的未来”,凭借其深度集成的 AI 能力&…...

面试官最爱问的Java多线程问题,你掌握了吗?

在当今软件开发领域,多线程编程已成为衡量一个开发者技术水平的重要标准之一。特别是在Java这一广泛使用的编程语言中,多线程能力更是面试官们青睐的考察点。掌握好Java多线程,不仅能提升程序性能,还能让你在众多求职者中脱颖而出…...

构建个人知识中枢:从信息孤岛到数字记忆宫殿的技术实践

1. 项目概述:一个为知识工作者打造的“数字记忆宫殿”同步工具最近在折腾个人知识管理(PKM)系统时,我遇到了一个几乎所有深度思考者都会面临的困境:信息碎片化。灵感可能来自手机备忘录、电脑上的Markdown笔记、网页剪…...

GIMP Resynthesizer:解决图像编辑中纹理合成难题的智能插件套件

GIMP Resynthesizer:解决图像编辑中纹理合成难题的智能插件套件 【免费下载链接】resynthesizer Suite of gimp plugins for texture synthesis 项目地址: https://gitcode.com/gh_mirrors/re/resynthesizer 你是否曾经在GIMP中尝试移除照片中的不需要元素&a…...

【开源源代码】基于 JeecgBoot低代码平台(v3.9.1)实现的金融科技信息门户网站(二次开发实践)

基于 JeecgBoot低代码平台(v3.9.1)实现的金融科技信息门户网站(二次开发实践)一、技术栈与版本1.1 后端技术栈技术版本选型理由Java17LTS 版本,性能稳定,支持虚拟线程Spring Boot3.2.x社区成熟,…...

跨越平台壁垒:TigerVNC如何让远程桌面体验如丝般顺滑

跨越平台壁垒:TigerVNC如何让远程桌面体验如丝般顺滑 【免费下载链接】tigervnc High performance, multi-platform VNC client and server 项目地址: https://gitcode.com/gh_mirrors/ti/tigervnc 你是否曾经因为无法远程访问办公室电脑而错过重要文件&…...

macOS Catalina Patcher:让老旧Mac电脑重获新生的终极指南 [特殊字符]

macOS Catalina Patcher:让老旧Mac电脑重获新生的终极指南 🚀 【免费下载链接】macos-catalina-patcher macOS Catalina Patcher (http://dosdude1.com/catalina) 项目地址: https://gitcode.com/gh_mirrors/ma/macos-catalina-patcher 还在为你的…...

跨平台智能消息机器人:基于大语言模型的多IM自动化实践

1. 项目概述与核心价值最近在折腾自动化工具时,发现了一个挺有意思的项目,叫“kunkeji/chatGPT_auto_msg_multiPlat”。光看名字,你大概能猜到它想干什么:一个能自动发送消息的机器人,并且支持多个平台,背后…...

EB Garamond 12:专业级开源复古字体深度解析与高级应用指南

EB Garamond 12:专业级开源复古字体深度解析与高级应用指南 【免费下载链接】EBGaramond12 项目地址: https://gitcode.com/gh_mirrors/eb/EBGaramond12 EB Garamond 12 是一款基于16世纪经典字体的开源复古字体,为设计师和开发者提供了免费获取…...

告别卡顿!手把手教你为Nvidia/AMD显卡在麒麟Kylin系统上安装正确驱动(附无线/蓝牙驱动修复)

麒麟Kylin系统显卡驱动优化与无线/蓝牙问题终极解决方案 开篇:为什么你的麒麟系统需要专属驱动优化? 刚装完麒麟Kylin操作系统的用户常会遇到两个"拦路虎":显卡性能拉胯导致动画卡顿、窗口拖影,以及无线网络/蓝牙设备…...

从一行配置看Linux安全基石:PAM机制深度解析与/etc/pam.d/su实战

从一行配置看Linux安全基石:PAM机制深度解析与/etc/pam.d/su实战 在Linux系统的安全架构中,认证机制如同城堡的第一道防线。当我们执行su命令切换用户时,背后默默工作的PAM(Pluggable Authentication Modules)系统往往…...

终极Visual C++运行库管理方案:VisualCppRedist AIO完全指南

终极Visual C运行库管理方案:VisualCppRedist AIO完全指南 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist VisualCppRedist AIO是一个专为Windows系统…...

如何完整保存任何网站:WebSite-Downloader终极指南

如何完整保存任何网站:WebSite-Downloader终极指南 【免费下载链接】WebSite-Downloader 项目地址: https://gitcode.com/gh_mirrors/web/WebSite-Downloader 在信息瞬息万变的互联网时代,你是否曾担心重要的在线内容突然消失?WebSit…...

我用免费AI,60天打造独立生意

Kristin Ginn 使用免费AI工具在60天内启动了她的咨询业务。她训练了2个生成式AI来角色扮演C-suite高管,帮助她测试想法。通过这种方法,她创建了商业资产、策划了销售策略,并更快地获得了客户。 我在企业营销领域工作了近十年,从未…...

AISMM质量保障不是流程,而是能力:SITS2026定义的6维成熟度诊断模型(附自测工具)

更多请点击: https://intelliparadigm.com 第一章:SITS2026专家:AISMM评估质量保障 AISMM(AI System Maturity Model)是SITS2026国际会议提出的面向生成式AI系统的成熟度评估框架,其核心目标是确保AI系统在…...

OpenMTP:重新定义macOS与Android文件传输体验的终极解决方案

OpenMTP:重新定义macOS与Android文件传输体验的终极解决方案 【免费下载链接】openmtp OpenMTP - Advanced Android File Transfer Application for macOS 项目地址: https://gitcode.com/gh_mirrors/op/openmtp 还在为macOS和Android设备之间的文件传输问题…...

通过taotoken cli工具一键配置开发团队的统一模型调用环境

通过taotoken cli工具一键配置开发团队的统一模型调用环境 为开发团队配置统一的大模型调用环境,通常涉及分发API密钥、设置基础URL、选择模型等一系列重复操作。手动配置不仅效率低下,还容易因成员操作差异导致环境不一致。Taotoken CLI工具&#xff0…...

通达信缠论插件终极指南:3步实现自动化缠论技术分析

通达信缠论插件终极指南:3步实现自动化缠论技术分析 【免费下载链接】ChanlunX 缠中说禅炒股缠论可视化插件 项目地址: https://gitcode.com/gh_mirrors/ch/ChanlunX 你是否曾被复杂的缠论分析困扰?手工绘制笔、线段、中枢耗时费力,主…...

题解:AtCoder AT_awc0063_e Number of Blocks in an Interval

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。 欢迎大…...

智能体通信协议SmartAgentProtocol:打破AI孤岛,构建标准化协作生态

1. 项目概述:一个面向智能体的通用通信协议最近在开源社区里,一个名为SmartAgentProtocol/smartagent的项目引起了我的注意。乍一看这个标题,你可能会觉得它又是一个关于“智能体”或“Agent”的框架,毕竟现在AI领域里各种Agent框…...

OpenClaw部署工具包:一键自动化安装与ROS集成指南

1. 项目概述:一个为“OpenClaw”项目量身定制的部署工具包如果你在开源社区里混迹过一段时间,特别是对机器人、机械臂或者自动化控制项目感兴趣,那么你很可能听说过“OpenClaw”这个名字。它通常指代一个开源的、模块化的机械爪或夹持器项目&…...

手把手复现一次完整的VPC内网渗透:从PHP-CGI漏洞到拿下域控的实战记录

从外网到域控:VPC环境下的渗透测试实战全解析 当企业将业务迁移到云端时,虚拟私有云(VPC)常被视为安全的堡垒。但真实情况是,任何网络环境都可能存在薄弱环节。本文将带您体验一次完整的渗透测试过程,从外网的一个看似普通的Web漏…...

Hearthstone-Script完整指南:免费自动化你的炉石传说游戏体验

Hearthstone-Script完整指南:免费自动化你的炉石传说游戏体验 【免费下载链接】Hearthstone-Script Hearthstone script(炉石传说脚本) 项目地址: https://gitcode.com/gh_mirrors/he/Hearthstone-Script Hearthstone-Script是一款完全…...

DeepSeek-V4本地部署全指南:vLLM分布式推理+量化配置

⚙️ 工程深度:L4 生产级 | 📖 预计阅读:30 分钟 为什么写这篇 很多工程师面对 DeepSeek-V4 的部署决策时,第一反应是"自建肯定比 API 贵"。这个直觉并不总是错的,但它忽略了一个基本事实:API 的成本随调用量线性增长,自建的成本是固定的。两条成本曲线必…...

不止于Demo:为SeamlessM4T模型快速搭建一个带鉴权的Flask API接口(附Nginx配置与文件访问)

从Demo到生产级服务:SeamlessM4T模型API工程化实战指南 当Meta发布SeamlessM4T这款支持近百种语言转录与翻译的一体化AI模型时,技术社区为之振奋。但许多开发者在兴奋之余也面临一个现实问题:如何将这项前沿技术从演示环境真正落地到生产系统…...

生产级 Agent 架构:限流、缓存、降级、监控全攻略

⚙️ 工程深度:L4 生产级 | 📖 预计阅读:28 分钟 一句话理解: Demo 跑通不算本事,稳定跑才算产品——限流防炸、缓存省钱、降级保命、监控兜底,四块砖垒起来才是生产地基。 🎯 本文产出 令牌桶限流 + 多租户隔离 + 三级降级完整代码(可直接集成,Python 3.11+) P…...

轻量级服务器控制面板ClawPanel:可视化Nginx与SSL证书管理实践

1. 项目概述:一个为开发者而生的轻量级控制面板最近在折腾自己的服务器时,总感觉传统的Web服务器管理方式有点“重”。无论是Nginx的配置文件,还是各种服务的状态监控,都得靠命令行敲来敲去,对于需要快速部署和演示的场…...