【MAC】Spring Boot 集成OpenLDAP(含本地嵌入式服务器方式)

目录

一、添加springboot ldap依赖:

二、本地嵌入式服务器模式

1.yml配置

 2.创建数据库文件:.ldif

3.实体类

4.测试工具类 

 5.执行测试

三、正常连接服务器模式

1.yml配置

2.连接LDAP服务器配置类,初始化连接,创建LdapTemplate 

3.创建admin用户条目映射类

 4.LdapUtil中添加测试方法

5.执行测试


一、添加springboot ldap依赖:

        <!--spring security ldap支持 做认证用,若不做认证只是测试连一下,可以不依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!--ldap依赖,版本建议和boot版本一致-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-ldap</artifactId>
        </dependency>
        <!--  unboundid-ldapsdk主要是为了在这里使用嵌入式的LDAP服务端来进行测试操作,所以scope设置为了test,
        实际应用中,会连接真实的、独立部署的LDAP服务器,不需要此项依赖。      -->
        <dependency>
            <groupId>com.unboundid</groupId>
            <artifactId>unboundid-ldapsdk</artifactId>
            <scope>test</scope>
        </dependency>

二、本地嵌入式服务器模式

在 Spring Boot 应用程序中,您可以使用 application.propertiesapplication.yml 来配置嵌入式 LDAP 服务器。当您使用 spring.ldap.embedded 配置属性时,Spring Boot 会尝试启动一个内嵌的 LDAP 服务器,并加载指定的 LDIF 文件作为初始数据。

 application.yml 配置如下内容:

spring:
  ldap:
    embedded:
      ldif: classpath:ldap-server.ldif
      base-dn: dc=testldap,dc=com
#classpath 意味着LDIF文件可以在任何标记为类路径的位置找到,而src/main/resources目录下的内容在构建过程中会被自动加入到类路径中。

这里是如何读取配置并启动内嵌的 LDAP 服务器:

  1. ldif: 这个字段指向一个 LDIF (LDAP Data Interchange Format) 文件。在这个例子中,它指向类路径下的 ldap-server.ldif 文件。Spring Boot 将会在应用启动时从这个文件加载数据到内嵌的 LDAP 服务器中。请确保该 LDIF 文件存在于您项目的资源目录下,例如 src/main/resources/ldap-server.ldif

  2. base-dn: 这是内嵌 LDAP 服务器使用的基本目录名称(Base DN)。在此示例中,所有的 LDAP 数据都将被加载至根目录 dc=testldap,dc=com 下。

当 Spring Boot 应用程序启动时,它会自动配置一个内嵌的 LDAP 服务器并加载 ldap-server.ldif 文件中定义的数据。不需要编写任何额外的代码来启动或初始化 LDAP 服务器;Spring Boot 的自动配置功能会处理这一切。

需要引入两个相关依赖:

unboundid-ldapsdk
spring-boot-starter-data-ldap

通过这种配置,您就可以在本地开发环境中模拟 LDAP 服务,而无需连接到真实的 LDAP 服务器。这在进行集成测试或本地开发时非常有用

1.yml配置

spring: #springboot的配置
  ldap:
    embedded:
      ldif: classpath:ldap-server.ldif
      base-dn: dc=testldap,dc=com
      port:8389 #默认839

如果ldap-server.ldif和application.yml在相同文件夹下,可以用相对路径,可以不加classpath

我这里配置的时候使用的是nacos 肯定不在相同文件夹下,需要加classpath

 2.创建数据库文件:.ldif

src/test/resources目录下创建ldap-server.ldif文件

文件内容

dn: dc=testldap,dc=com
objectClass: top
objectClass: domain

dn: ou=users,dc=testldap,dc=com
objectclass: top
objectclass: organizationalUnit
ou: people

dn: uid=1,ou=users,dc=testldap,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: zhangsan
sn: zhang
uid: 1
userPassword: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=

3.实体类(条目映射)


import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;

import javax.naming.Name;

/**
 * @version v1.0
 * @className LdapUser
 * @description  与 LADP存储内容进行映射
 */
@Entry(
        base = "ou=users,dc=testldap,dc=com",
        objectClasses = {"top", "person", "organizationalPerson", "inetOrgPerson"}
)
@Data
public class LdapUserinfo {
    @Id
    @JsonIgnore
    private Name id; // LDAP Distinguished Name (DN)

    @Attribute(name = "cn") // Common Name
    private String realName;

    @Attribute(name = "mobile") // Mobile number
    private String phone;

    @Attribute(name = "userPassword")
    private String password;

    @Attribute(name = "mail") // E-mail address
    private String emailAddr;

    @Attribute(name = "uid")
    private String userId;

}

4.测试工具类 


import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.query.ContainerCriteria;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.stereotype.Component;

/**
 * @version v1.0
 * @className LdapUtil
 * @date 2024/5/14
 */
@Slf4j
@Component
public class LdapUtil {
    @Autowired
    private LdapTemplate ldapTemplate;
    @Value("${spring.ldap.embedded.base-dn}") 
    private String baseRoot;//从nacos读取的 为了验证能否正常读取nacos,可以不写


    public LdapUserinfo findUser(String base,String userId, String password) {
        // 根据uid 和密码 查询用户是否存在
        log.info("---findUser---userName={} password={} baseRoot={}", userId,password,baseRoot);
        LdapUserinfo userinfo = null;
        EqualsFilter filter = new EqualsFilter("uid", userId);
        base = "ou=users,dc=testldap,dc=com";
       boolean bool = ldapTemplate.authenticate(baseRoot, filter.toString(), password);
        if (bool) {
            // 构建查询条件
            LdapQueryBuilder builder = LdapQueryBuilder.query();
            // 根据 uid查询
            builder.where("uid").is(userId);
            // 注意LdapUserinfo 类,一定要跟 ldap协议中的属性名称对应
            userinfo = ldapTemplate.findOne(builder, LdapUserinfo.class);
            log.info("LdapUserinfo:" + JSONUtil.toJsonStr(userinfo));
        } else {
            log.info("未查询到用户");
        }
        return userinfo;
    }

    public void findUser() {
        // 构建查询条件
        LdapQueryBuilder builder = LdapQueryBuilder.query();
        //builder.base("dc=testldap,dc=com"); yml中已经指定了,这里不需要再指定,重复指定会导致路径解析问题
        // 根据 uid查询
        builder.where("cn").is("admin");
        // 注意LdapUserinfo 类,一定要跟 ldap协议中的属性名称对应
        AdminUser userinfo = ldapTemplate.findOne(builder, AdminUser.class);
        log.info("LdapUserinfo:" + JSONUtil.toJsonStr(userinfo));
    }

}

注:yml中已经指定了base,不需要再指定,重复指定会导致路径解析问题。尽量为空

 5.执行测试

将testldap.ldif中的内容打印出来了

debug时测试内置服务器连接,此时本地的嵌入式服务器是联通的

参考链接:Spring Boot中使用LDAP来统一管理用户信息_ldapquery-CSDN博客 

三、正常连接服务器模式

mac安装openldap详见:Mac上安装OpenLDAP服务器详细教程(Homebrew安装和自带的ldap)-CSDN博客

1.yml配置

spring: #springboot的配置
  ldap:
    urls: ldap://localhost:389
    base: dc=testldap,dc=com
    username: cn=admin,dc=testldap,dc=com
    password: secret

2.连接LDAP服务器配置类,初始化连接,创建LdapTemplate 


import org.springframework.beans.factory.annotation.Value;
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;
import java.util.HashMap;
import java.util.Map;

/**
 * @version v1.0
 * @className LdapConfig
 * @date 2024/5/21
 * @description 开发配置类LdapConfiguration,初始化连接,创建LdapTemplate
 */
@Configuration
public class LdapConfig {
    private LdapTemplate ldapTemplate;
    @Value("${spring.ldap.urls}")
    private String url;
    @Value("${spring.ldap.base}")
    private String base;
    @Value("${spring.ldap.username}")
    private String username;
    @Value("${spring.ldap.password}")
    private String password;
    @Bean
    public LdapContextSource contextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        Map<String, Object> config = new HashMap();
        contextSource.setUrl(url);
        contextSource.setBase(base);
        contextSource.setUserDn(username);// 例:管理员DN
        contextSource.setPassword(password);// 例:管理员密码
        //  解决乱码
        config.put("java.naming.ldap.attributes.binary", "objectGUID");
        // 启动时不立即初始化(lazy connection initializing),直到第一次LDAP操作
        contextSource.setPooled(true);
        // 调用afterPropertiesSet方法是必须的,它会处理配置并创建初始连接
        contextSource.setBaseEnvironmentProperties(config);
        return contextSource;
    }
    @Bean
    public LdapTemplate ldapTemplate() {
        if (null == ldapTemplate) {
            ldapTemplate = new LdapTemplate(contextSource());
        }
        return ldapTemplate;
    }
}

3.创建admin用户条目映射类

根据LDAP 数据结构,你可以创建一个映射到 admin 用户条目的 Java 类。这个类需要使用 Spring LDAP ODM(Object-Directory Mapping)来映射 LDAP 条目的属性到 Java 对象的属性。

根据ldif文件条目设置字段

# testldap.com
dn: dc=testldap,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Organization
dc: testldap

# admin, testldap.com
dn: cn=admin,dc=testldap,dc=com
objectClass: organizationalRole
cn: admin

@Entry(objectClasses = {"organizationalRole"})


import lombok.Data;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;

import javax.naming.ldap.LdapName;

@Entry(objectClasses = {"organizationalRole"})
@Data
public class AdminUser {
    @Id
    private LdapName dn; // LDAP Distinguished Name (DN)

    @Attribute(name = "cn")
    private String commonName;
}

 4.LdapUtil中添加测试方法

    public void findUser() {
        // 构建查询条件
        LdapQueryBuilder builder = LdapQueryBuilder.query();
        //builder.base("dc=testldap,dc=com");
        // 根据 uid查询
        builder.where("cn").is("admin");
        // 注意LdapUserinfo 类,一定要跟 ldap协议中的属性名称对应
        AdminUser userinfo = ldapTemplate.findOne(builder, AdminUser.class);
        log.info("LdapUserinfo:" + JSONUtil.toJsonStr(userinfo));
    }

5.执行测试

打印结果如下:

参考链接:springboot 整合 LDAP-阿里云开发者社区

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/659238.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android framework修改,禁止指定包名的apk安装到设备上(基于Android10.0.0-r41)

文章目录 Android framework修改&#xff0c;禁止指定包名的apk安装到设备上(基于Android10.0.0-r41)1.新增接口提供给上层调用2.在pms中实现新增的接口3.找到preparePackageLI方法。4.测试验证 Android framework修改&#xff0c;禁止指定包名的apk安装到设备上(基于Android10…

如何利用短链接巧妙避开多渠道推广大坑

在当下&#xff0c;推广渠道多样化对企业来说&#xff0c;那可是机遇与大坑并存&#xff01;多渠道推广的重要性大家都懂&#xff0c;但为啥说有坑呢&#xff1f;一旦企业开启多渠道推广模式&#xff0c;就得面对大量人力物力的投入&#xff0c;可要是区分不了各个渠道的推广效…

超详细介绍基于微调 Faster R-CNN实现海上航拍图像中检测小物体-含源码与数据集免费下载

在航拍图像中检测小物体,尤其是对于海上救援等关键应用而言,是一项独特的挑战。及时检测水中的人可能意味着生死之间的差别。我们的研究重点是微调 Faster R-CNN(一种强大的两阶段物体检测器),以满足这一重要需求。 我们研究的核心是SeaDroneSee 数据集,这是一组重要的图…

【NumPy】全面解析add函数:高效数组加法操作

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

源达投顾的投资建议可不可信?

在金融投资领域&#xff0c;专业的投资顾问机构如源达投顾&#xff0c;为投资者提供了宝贵的投资建议和策略。然而&#xff0c;面对市场上众多的投资顾问机构&#xff0c;投资者往往会产生疑问&#xff1a;源达投顾的投资建议真的可信吗&#xff1f; 一、专业团队背景 源达投…

MSC Apex压力容器应力线性化的应用方法

应力线性化是针对压力容器设计常用的一种技术。在工程领域&#xff0c;应力线性化在分析复杂载荷条件下构件的结构完整性方面起着至关重要的作用。准确的应力线性化对于评估是否符合行业标准(如美国机械工程师协会(ASME)制定的标准)至关重要。为了简化应力线性化的过程&#xf…

HTML+CSS+JS简易计算器

HTMLCSSJS简易计算器 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>简易计算器</t…

探索Django 5: 从零开始,打造你的第一个Web应用

今天我们将一起探索 Django 5&#xff0c;一个备受开发者喜爱的 Python Web 框架。我们会了解 Django 5 的简介&#xff0c;新特性&#xff0c;如何安装 Django&#xff0c;以及用 Django 编写一个简单的 “Hello, World” 网站。最后&#xff0c;我会推荐一本与 Django 5 相关…

JAVAEE之多线程进阶(2)_ CAS概念、实现原理、ABA问题及解决方案

前言 在并发编程时&#xff0c;常常会出现线程安全问题&#xff0c;那么如何保证原子性呢&#xff1f;常用的方法就是加锁。在Java语言中可以使用 Synchronized和CAS实现加锁效果。  Synchronized关键字保证同步的&#xff0c;这会导致有锁&#xff0c;但是锁机制存在以下问题…

慧尔智联携纷享销客启动CRM项目 推进客户经营升级与内外高效协作

智慧农业领军企业慧尔智联携手纷享销客&#xff0c;启动CRM客户经营管理系统项目。双方将深入合作&#xff0c;全面落实慧尔智联发展策略&#xff0c;持续提升数字化经营管理水平&#xff0c;实现内部团队信息化高效协作&#xff0c;以快速响应市场需求&#xff0c;提升客户满意…

竹云董事长在第二届ICT技术发展与企业数字化转型高峰论坛作主题演讲

5月25日&#xff0c;由中国服务贸易协会指导&#xff0c;中国服务贸易协会信息技术服务委员会主办的 “第二届ICT技术发展与企业数字化转型高峰论坛” 在北京隆重召开。 本次论坛以 “数据驱动&#xff0c;AI引领&#xff0c;打造新质生产力” 为主题&#xff0c;特邀业内200余…

hadoop hdfs优势和缺点

hdfs优点 高容错性适合处理大数据可构建再廉价的机器上 hdfs缺点 不适合做低延迟数据访问 毫秒级的存储数据做不到 无法高效的对大量小文件进行存储不支持并发写入 文件随机修改 一个文件只能有一个writer 不允许多个线程同时写仅支持数据追加 不支持文件的随机修改 hdf…

队列的特性及代码实现(C语言)

目录 队列的定义 队列的实现分析 代码实现 Queue.h Queue.c 队列的定义 队列是只允许在一端进行插入操作&#xff0c;而在另一段进行删除操作的线性表。 首先&#xff0c;让我们来看一看生活中的队列&#xff0c;当我们去银行办理业务的时候&#xff0c;我们进入银行的时候…

TPK系列——2W 3KVDC 隔离单,双输出 DC/DC 电源模块

TPK系列是一款2W并且有高隔离电压要求的理想产品&#xff0c;工业级温度范围–40℃到 105℃&#xff0c;在此温度范围内都可以稳定输出2W&#xff0c;并且效率非常高&#xff0c;高达89%&#xff0c;同时负载调整率非常低&#xff0c;对于有输出电压精度有要求的地方特别合适&a…

服务案例|网络攻击事件的排查与修复

LinkSLA智能运维管家V6.0版支持通过SNMP Trap对设备进行监控告警&#xff0c;Trap是一种主动推送网络设备事件或告警消息的方式&#xff0c;与SNMP轮询&#xff08;polling&#xff09;不同&#xff0c;具有以下几点优势&#xff1a; 1. 实时监控与快速响应 SNMP Trap能够实时…

LeetCode 518.零钱兑换Ⅱ

思路&#xff1a; 这题和之前做的不大一样&#xff0c;之前的动态规划转化成背包问题一般都是求能放入的最大重量&#xff0c;这个是求组合数。 求组合数的状态转移方程之前在1和0提到过&#xff1a; dp[j]dp[j-nums[]i]; 这里重点分析一下遍历顺序&#xff1a; 这段代码里面是…

vue学习汇总

目录 一、vue基本语法 1.插值表达式 {{}} 2.显示数据(v-text)和(v-html) 3.事件处理(v-on) 4.循环遍历(v-for) 5.判断语法(v-if) 6.元素显示与隐藏(v-show) 7.动态设置属性(v-bind) 8.数据双向绑定(v-model) 9.计算属性 二、vue组件 1.使用组件的三个步骤 2.注册组…

Spring Boot发送邮件时如何支持定时功能?

如何使用Spring Boot结合AokSend以实现高效邮件发送&#xff1f; 如何高效地进行sendmail发送邮件并支持定时功能是一个值得探讨的问题。本文将详细介绍如何在Spring Boot中实现定时sendmail发送邮件&#xff0c;并结合AokSend工具实现高效邮件发送。 Spring Boot发送邮件&am…

【Go专家编程——并发控制——三剑客】

并发控制 我们考虑这么一种场景&#xff0c;协程在A执行过程中需要创建子协程A1、A2、A3…An&#xff0c;协程创建完子协程后就等待子协程退出。 针对这种场景&#xff0c;Go提供了三种解决方案&#xff1a; Channel&#xff1a;使用channel控制子协程 优点&#xff1a;实现…

6.1 Go 数组

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…