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

java连接ldap实现查询

在这里插入图片描述

文章目录

  • 一、项目背景
  • 二、准备工作
  • 三、验证结果
  • 四、易错点讲解
    • 易错点1:java: 无法访问org.springframework.ldap.core.LdapTemplate
    • 易错点2:java: 无法访问org.springframework.context.ConfigurableApplicationContext
    • 易错点3:[LDAP: error code 34 - invalid DN]
    • 易错点4:LDAP: error code 32 - No Such Object
    • 易错点5:配置文件介绍

一、项目背景

我们公司原项目是Spring或者SpringBoot项目,现在假设收购了一家公司(人家所有账户信息都保存在ldap数据库中),现在需要把它集成进来,最终实现项目支持两种方式认证:

  • 如果是http协议执行从mysql数据库查询账户,校验用户+密码
  • 另一种如果是ldap协议,则从ldap中查询账户,校验用户+密码

目前我的项目版本:

  • Spring版本:5.3.15
  • SpringBoot版本:2.6.3

二、准备工作

test.ldif文件 用于创建账户

注意点1:必须先创建组,然后才能创建组下用户,不然cn=ldapUser1,ou=Develop,ou=Hytera,dc=yaobili,dc=com这么写是非法的
注意点2:我创建了2个账户,ldapUser1账户1密码未加密Eadmin123456,ldapUser2账户2密码加密了设置的{SSHA}J3NuHvl3O8LdPuV2QFYc2pPy3wq1EzIN,它两都是相同的密码(即Eadmin123456和{SSHA}J3NuHvl3O8LdPuV2QFYc2pPy3wq1EzIN是等价的)
注意点3:其中的{SSHA}代表采用SHA-1加密方式对密码进行了加密,详情可在服务器执行如下命令

[root@localhost ~]# slappasswd -s Eadmin123456
{SSHA}J3NuHvl3O8LdPuV2QFYc2pPy3wq1EzIN
创建组织架构
dn:ou=Hytera,dc=yaobili,dc=com
objectClass:organizationalUnit
ou:Hyteradn:ou=Develop,ou=Hytera,dc=yaobili,dc=com
objectClass:organizationalUnit
ou:Develop创建用户
dn: cn=ldapUser1,ou=Develop,ou=Hytera,dc=yaobili,dc=com
objectClass: inetOrgPerson
cn: ldapUser1
username: ldapUser1
userPassword: Eadmin123456
memberOf: ou=Develop,ou=Hytera,dc=yaobili,dc=comdn: cn=ldapUser2,ou=Develop,ou=Hytera,dc=yaobili,dc=com
objectClass: inetOrgPerson
cn: ldapUser2
username: ldapUser2
userPassword: Eadmin123456
memberOf: ou=Develop,ou=Hytera,dc=yaobili,dc=comdn: cn=ldapUser4,ou=Develop,ou=Hytera,dc=yaobili,dc=com
objectClass: inetOrgPerson
cn: ldapUser4
username: ldapUser4
userPassword: {SSHA}J3NuHvl3O8LdPuV2QFYc2pPy3wq1EzIN
memberOf: ou=Develop,ou=Hytera,dc=yaobili,dc=com

成功后页面长这样:

在这里插入图片描述

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springboot-test</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>Ldap-test</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!--解决@RestController注解爆红--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring.boot.starter.web.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency><!--测试类--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${spring.boot.starter.test.version}</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-ldap</artifactId><version>2.6.3</version></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-ldap</artifactId><version>2.6.3</version></dependency><dependency><groupId>com.sun</groupId><artifactId>ldapbp</artifactId><version>1.0</version><scope>provided</scope></dependency><dependency><groupId>org.springframework.ldap</groupId><artifactId>spring-ldap-core</artifactId><version>2.4.0</version></dependency><dependency><groupId>org.apache.directory.api</groupId><artifactId>api-all</artifactId><version>2.0.0</version></dependency></dependencies>
</project>

application.properties

server.port=8020spring.ldap.urls=ldap://10.110.38.162:389
spring.ldap.username=cn=admin,dc=yaobili,dc=com
spring.ldap.password=123456
spring.ldap.base=dc=yaobili,dc=com

LdapConfiguration配置类

package com.ldap.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import java.util.Objects;/*** LDAP 的自动配置类* @Author 211145187* @Date 2024/5/21 16:44**/
@Configuration
public class LdapConfiguration {private static Logger logger = LoggerFactory.getLogger(LdapConfiguration.class);private LdapTemplate ldapTemplate;@Value("${spring.ldap.urls}")private String dbUrl;@Value("${spring.ldap.username}")private String username;@Value("${spring.ldap.password}")private String password;@Value("${spring.ldap.base}")private String base;@Beanpublic LdapContextSource contextSource() {LdapContextSource contextSource = new LdapContextSource();Map<String, Object> config = new HashMap();contextSource.setUrl(dbUrl);contextSource.setBase(base);contextSource.setUserDn(username);contextSource.setPassword(password);//  解决 乱码 的关键一句config.put("java.naming.ldap.attributes.binary", "objectGUID");contextSource.setPooled(true);contextSource.setBaseEnvironmentProperties(config);return contextSource;}@Beanpublic LdapTemplate ldapTemplate(LdapContextSource contextSource) {if (Objects.isNull(contextSource)) {throw new RuntimeException("ldap contextSource error");}if (null == ldapTemplate) {ldapTemplate = new LdapTemplate(contextSource);}return ldapTemplate;}
}

LdapUserAttributeMapper映射类

package com.ldap.mapper;import com.ldap.entity.LdapUser;
import org.springframework.ldap.core.AttributesMapper;import javax.naming.NamingException;
import javax.naming.directory.Attributes;/*** 将ldap返回的结果,转成指定对象*/
public class LdapUserAttributeMapper implements AttributesMapper {/*** 将单个Attributes转成单个对象* @param attrs* @return* @throws NamingException*/@Overridepublic Object mapFromAttributes(Attributes attrs) throws NamingException {LdapUser user  = new LdapUser();if(attrs.get("uid") != null){user.setUid( attrs.get("uid").get().toString());}if(attrs.get("cn") != null){user.setCn( attrs.get("cn").get().toString());}if(attrs.get("dn") != null){user.setDn( attrs.get("dn").get().toString());}if(attrs.get("sn") != null){user.setSn( attrs.get("sn").get().toString());}if(attrs.get("userPassword") != null){user.setUserPassword(new String((byte[])attrs.get("userPassword").get()));}return user;}
}

LdapUser实体类

package com.ldap.entity;import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;/*** @Author 211145187* @Date 2024/5/22 09:31**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LdapUser {private String uid;private String dn;private String cn;private String sn;private String userPassword;
}

LdapTest测试类

package com.ldap;import com.ldap.entity.LdapUser;
import com.ldap.mapper.LdapUserAttributeMapper;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.test.context.junit4.SpringRunner;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;@SpringBootTest
@RunWith(SpringRunner.class)
public class LdapTest {@Autowiredprivate LdapTemplate ldapTemplate;@Testpublic void listUsers() throws NoSuchAlgorithmException {AndFilter filter = new AndFilter();filter.and(new EqualsFilter("objectClass", "inetOrgPerson"));List<LdapUser> users = ldapTemplate.search("ou=Develop,ou=Hytera", filter.encode(), new LdapUserAttributeMapper());for (LdapUser user: users ) {System.out.println("user: " + user);System.out.println("userPassword:" + user.getUserPassword());System.out.println(verifySHA(user.getUserPassword(), "Eadmin123456"));}//        Assert.assertEquals(123, users.size());}@SuppressWarnings(value = "unchecked")public static boolean verifySHA(String ldappw, String inputpw)throws NoSuchAlgorithmException {// MessageDigest 提供了消息摘要算法,如 MD5 或 SHA,的功能,这里LDAP使用的是SHA-1MessageDigest md = MessageDigest.getInstance("SHA-1");// 取出加密字符if (ldappw.startsWith("{SSHA}")) {ldappw = ldappw.substring(6);} else if (ldappw.startsWith("{SHA}")) {ldappw = ldappw.substring(5);}// 解码BASE64byte[] ldappwbyte = Base64.decode(ldappw);byte[] shacode;byte[] salt;// 前20位是SHA-1加密段,20位后是最初加密时的随机明文if (ldappwbyte.length <= 20) {shacode = ldappwbyte;salt = new byte[0];} else {shacode = new byte[20];salt = new byte[ldappwbyte.length - 20];System.arraycopy(ldappwbyte, 0, shacode, 0, 20);System.arraycopy(ldappwbyte, 20, salt, 0, salt.length);}// 把用户输入的密码添加到摘要计算信息md.update(inputpw.getBytes());// 把随机明文添加到摘要计算信息md.update(salt);// 按SSHA把当前用户密码进行计算byte[] inputpwbyte = md.digest();// 返回校验结果return MessageDigest.isEqual(shacode, inputpwbyte);}}

三、验证结果

在这里插入图片描述
结论:从结果可以看出确实读出来了,而且我也把密码打印出来了。

接下来对打印结果进行讲解

代码

@Testpublic void listUsers() throws NoSuchAlgorithmException {AndFilter filter = new AndFilter();filter.and(new EqualsFilter("objectClass", "inetOrgPerson"));List<LdapUser> users = ldapTemplate.search("ou=Develop,ou=Hytera", filter.encode(), new LdapUserAttributeMapper());for (LdapUser user: users ) {System.out.println("user: " + user);System.out.println("userPassword:" + user.getUserPassword());System.out.println(verifySHA(user.getUserPassword(), "Eadmin123456"));}}

我的需求:假设页面传入了用户名和密码,然后我想从ldap读取所有账户信息,进行账户+密码的比对是否相等,做这么个事儿。

四、易错点讲解

易错点1:java: 无法访问org.springframework.ldap.core.LdapTemplate

完整错误:

java: 无法访问org.springframework.ldap.core.LdapTemplate错误的类文件: /E:/apache-maven-3.6.3/repository/org/springframework/ldap/spring-ldap-core/3.2.3/spring-ldap-core-3.2.3.jar!/org/springframework/ldap/core/LdapTemplate.class类文件具有错误的版本 61.0, 应为 52.0请删除该文件或确保该文件位于正确的类路径子目录中。

错误原因:引入的依赖版本和Spring版本或者SpringBoot版本不适配(大白话讲:你引入的版本太高了)
我最开始的依赖版本用的是最新的,因为习惯性添加依赖就会莫名添加最新的,结果问题就是它导致的。

<dependency><groupId>org.springframework.ldap</groupId><artifactId>spring-ldap-core</artifactId><version>3.2.3</version>
</dependency>       

解决方案:选择适配的即可,最终可以使用的版本

<dependency><groupId>org.springframework.ldap</groupId><artifactId>spring-ldap-core</artifactId><version>2.4.0</version>
</dependency>

易错点2:java: 无法访问org.springframework.context.ConfigurableApplicationContext

完整错误:

java: 无法访问org.springframework.context.ConfigurableApplicationContext错误的类文件: /E:/apache-maven-3.6.3/repository/org/springframework/spring-context/6.1.7/spring-context-6.1.7.jar!/org/springframework/context/ConfigurableApplicationContext.class类文件具有错误的版本 61.0, 应为 52.0请删除该文件或确保该文件位于正确的类路径子目录中。

错误原因:引入的依赖版本和Spring版本或者SpringBoot版本不适配(大白话讲:你引入的版本太高了)
我最开始的依赖版本用的是最新的,因为习惯性添加依赖就会莫名添加最新的,结果问题就是它导致的。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-ldap</artifactId><version>3.3.0</version>
</dependency>
<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-ldap</artifactId><version>3.3.0</version>
</dependency>

解决方案:选择适配的即可,最终可以使用的版本

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-ldap</artifactId><version>2.6.3</version>
</dependency>
<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-ldap</artifactId><version>2.6.3</version>
</dependency>

易错点3:[LDAP: error code 34 - invalid DN]

在这里插入图片描述

完整错误

org.springframework.ldap.InvalidNameException: [LDAP: error code 34 - invalid DN]; nested exception is javax.naming.InvalidNameException: [LDAP: error code 34 - invalid DN]at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:136)at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:363)at org.springframework.ldap.core.support.AbstractContextSource.doGetContext(AbstractContextSource.java:147)at org.springframework.ldap.core.support.AbstractContextSource.getReadOnlyContext(AbstractContextSource.java:166)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:361)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:332)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:608)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:598)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:486)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:502)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:518)at com.ldap.LdapTest.listUsers(LdapTest.java:31)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)at org.junit.runners.ParentRunner.run(ParentRunner.java:413)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: javax.naming.InvalidNameException: [LDAP: error code 34 - invalid DN]at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3095)at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2886)at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2800)at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:319)at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)at javax.naming.InitialContext.init(InitialContext.java:244)at javax.naming.ldap.InitialLdapContext.<init>(InitialLdapContext.java:154)at org.springframework.ldap.core.support.LdapContextSource.getDirContextInstance(LdapContextSource.java:42)at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:351)... 41 more

代码长这样:

application.properties

spring.ldap.urls=ldap://10.110.38.162:389
spring.ldap.username=admin
spring.ldap.password=123456
spring.ldap.base=dc=yaobili,dc=com

LdapTest

@Testpublic void listUsers() throws NoSuchAlgorithmException {AndFilter filter = new AndFilter();filter.and(new EqualsFilter("objectClass", "inetOrgPerson"));List<LdapUser> users = ldapTemplate.search("ou=Develop,ou=Hytera", filter.encode(), new LdapUserAttributeMapper());for (LdapUser user: users ) {System.out.println("user: " + user);System.out.println("userPassword:" + user.getUserPassword());System.out.println(verifySHA(user.getUserPassword(), "Eadmin123456"));}}

错误原因:配置文件中spring.ldap.username这里错了,因为我创建了admin管理员账户,但是这里我不知道是输入admin 啊还是输入完整dn

解决方案:此处应该输入完整dn:spring.ldap.username=cn=admin,dc=yaobili,dc=com

易错点4:LDAP: error code 32 - No Such Object

在这里插入图片描述

完整错误

org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - No Such Object]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - No Such Object]; remaining name 'ou=Develop,ou=Hytera,dc=yaobili,dc=com'at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:183)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:380)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:332)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:608)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:598)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:486)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:502)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:518)at com.ldap.LdapTest.listUsers(LdapTest.java:31)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:498)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)at org.junit.runners.ParentRunner.run(ParentRunner.java:413)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)at org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: javax.naming.NameNotFoundException: [LDAP: error code 32 - No Such Object]; remaining name 'ou=Develop,ou=Hytera,dc=yaobili,dc=com'at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3179)at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3100)at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2891)at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1846)at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1769)at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:392)at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:358)at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:341)at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:267)at org.springframework.ldap.core.LdapTemplate$4.executeSearch(LdapTemplate.java:326)at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:367)... 38 more

错误代码:

application.properties

spring.ldap.urls=ldap://10.110.38.162:389
spring.ldap.username=cn=admin,dc=yaobili,dc=com
spring.ldap.password=123456
spring.ldap.base=ou=Develop,ou=Hytera,dc=yaobili,dc=com

LdapTest

@Testpublic void listUsers() throws NoSuchAlgorithmException {AndFilter filter = new AndFilter();filter.and(new EqualsFilter("objectClass", "inetOrgPerson"));List<LdapUser> users = ldapTemplate.search("ou=Develop,ou=Hytera,dc=yaobili,dc=com", filter.encode(), new LdapUserAttributeMapper());for (LdapUser user: users ) {System.out.println("user: " + user);System.out.println("userPassword:" + user.getUserPassword());System.out.println(verifySHA(user.getUserPassword(), "Eadmin123456"));}}

疑惑:32错误码对应dn设置不对,但是我感觉不出来哪里不对啊,感觉spring.ldap.base和ldapTemplate.search都设置了正确的dn 啊,而且"ou=Develop,ou=Hytera,dc=yaobili,dc=com"这个dn就是我要查询账户所在的完整dn路径啊,不信看图。
在这里插入图片描述

错误原因:spring.ldap.base和ldapTemplate.search是有传递行的(你可以理解为拼接的效果,一因此不能设置一样的否则就乱套了,找不到了)。这易错点特别操蛋,因为根本别人的博客找不到还有这个规则说明,上来就是给你贴配置类文件和代码,然后照抄运行就报错,关键他们也不贴运行结果,我就只能挨个尝试去试错。

解决方案

  • 如果spring.ldap.base设置了spring.ldap.base=“ou=Develop,ou=Hytera,dc=yaobili,dc=com”,那么search方法构面跟的就应该是空字符串“”)
spring.ldap.base=ou=Develop,ou=Hytera,dc=yaobili,dc=com
List<LdapUser> users = ldapTemplate.search("", filter.encode(), new LdapUserAttributeMapper());
  • 如果spring.ldap.base设置了spring.ldap.base=dc=yaobili,dc=com,那么search方法构面跟的就应该是"ou=Develop,ou=Hytera"
spring.ldap.base=dc=yaobili,dc=com
List<LdapUser> users = ldapTemplate.search("ou=Develop,ou=Hytera", filter.encode(), new LdapUserAttributeMapper());

易错点5:配置文件介绍

spring.ldap.urls=ldap://10.110.38.162:389
spring.ldap.username=cn=admin,dc=yaobili,dc=com
spring.ldap.password=123456
spring.ldap.base=dc=yaobili,dc=com
  • spring.ldap.urls配置url,端口分两种:389和3268
    • 端口 389:这是 LDAP(轻量级目录访问协议)的标准端口号。通常,LDAP 服务器使用此端口号来监听 LDAP 请求。大多数基于 LDAP 的应用程序和工具都默认使用此端口号来与 LDAP 服务器通信。
    • 端口 3268:这是全局目录服务接口(Global Catalog Service)的端口号。全局目录是 Active Directory 的一部分,它包含了多个域的数据。端口 3268 允许在全局目录上进行查询,而不仅仅是在单个域中。这使得可以在整个 Active Directory 环境中执行查询操作。
  • spring.ldap.username配置管理元用户名,此处只能输入管理员账户的完整dn,即必须输入cn=admin,dc=yaobili,dc=com才有效,而配置admin会导致无法登陆
  • spring.ldap.password配置密码,这里我试过了,只能配置未加密密码,配置加密密码也会导致无法登陆。
  • spring.ldap.base用于配置 LDAP 查询的基础路径(Base DN)的属性。Base DN 是 LDAP 查询的起始点,它指定了在搜索 LDAP 目录时的起始位置。

相关文章:

java连接ldap实现查询

文章目录 一、项目背景二、准备工作三、验证结果四、易错点讲解易错点1&#xff1a;java: 无法访问org.springframework.ldap.core.LdapTemplate易错点2&#xff1a;java: 无法访问org.springframework.context.ConfigurableApplicationContext易错点3&#xff1a;[LDAP: error…...

openjudge_2.5基本算法之搜索_2990:符号三角形

题目 2990:符号三角形 总时间限制: 1000ms 内存限制: 65536kB 描述 符号三角形的第1行有n个由“”和”-“组成的符号 &#xff0c;以后每行符号比上行少1个&#xff0c;2个同号下面是”“&#xff0c;2个异号下面是”-“ 。计算有多少个不同的符号三角形&#xff0c;使其所含”…...

springboot错误

错误总结 1、使用IDEA 的 initialalzer显示2、IDEA 新建文件 没有 java class3、java: 错误: 不支持发行版本 22解决方法4、IDEA-SpringBoot项目yml配置文件不自动提示解决办法 1、使用IDEA 的 initialalzer显示 IDEA创建SpringBoot项目时出现&#xff1a;Initialization fail…...

linux的用户管理

新建用户&#xff1a;1.useradd 2.passwd 完成的操作&#xff1a; (1)/etc/passwd添加一行 (2)/etc/shadow添加一行 (3)/etc/group添加一行 (4)创建用户家目录 (5)创建用户邮件文件 例&#xff1a;创建用户jerry&#xff0c;要求: uid:777&am…...

数美滑块研究

周一&#xff0c;在清晨的阳光照耀下&#xff0c;逆向山脚下的小镇宁静而安详。居民们忙碌地开始一天的生活&#xff0c;而在爬虫镇子的边缘&#xff0c;一座古朴的道观显得格外神秘。 阿羊正静静地坐在青石长凳上&#xff0c;摸鱼养神。突然&#xff0c;一道清脆的声音在他耳…...

【GESP试卷】2024年03月Scratch四级试卷

2024年GESP03月认证Scratch四级试卷 分数&#xff1a;100 题数&#xff1a;27 一、单选题(共15题&#xff0c;每题2分&#xff0c;共30分) 010203040506070809101112131415CDBBACBCDCDADBA 1、小杨的父母最近刚刚给他买了一块华为手表&#xff0c;他说手表上跑的是鸿蒙&…...

每日一题《leetcode--398.随机数索引》

https://leetcode.cn/problems/random-pick-index/ 根据题目所知&#xff0c;所给的数组中有重复的元素。让我们随机输出给定的目标数字的下标索引。 typedef struct {int *sum;int length; } Solution;Solution* solutionCreate(int* nums, int numsSize) {Solution* obj (So…...

【MySQL精通之路】MySQL的使用(9)-设置环境变量

可以在命令提示符下设置环境变量&#xff0c;以影响命令处理器的当前调用&#xff0c;也可以永久设置环境变量以影响未来的调用。 要永久设置变量&#xff0c;可以在启动文件中进行设置&#xff0c;也可以使用系统为此提供的接口进行设置。 有关具体细节&#xff0c;请参阅命…...

JDBC(Java DataBase Connectivity)Java数据库连接

JDBC(Java DataBase Connectivity) Java 语言连接数据库 再本模块中,java提供里一组用于连接数据库的类和接口Java 语言开发者,本身没有提供如何具体连接数据库的功能只是定义了一组java程序连接数据库的访问接口 连接到数据库向数据库发送增,修改,删除这一类的sql发送查询sq…...

1.Redis之初识Redis分布式系统

1.初识Redis 1.1 官网 Redis中文网 Redis 教程 | 菜鸟教程 (runoob.com) 1.2 解释 在内存中存储数据 定义变量,不就是在内存中存储数据嘛?? Redis 是在分布式系统&#xff08;进程的隔离性&#xff1a;Redis 就是基于网络&#xff0c;可以把自己内存中的变量给别的进程…...

基于SpringBoot的网盘系统设计与实现

第1章 绪论... 1 1.1 研究背景与意义... 1 1.1.1 研究背景... 1 1.1.1 研究意义... 1 1.2 国内外研究现状... 2 1.2.1 国内研究现状... 2 1.2.2 国外研究现状... 3 1.3 论文组织架构... 4 第2章 关键技术介绍... 5 2.1 SpringBoot. 5 2.2 MySQL数据库... 5 2.3 MVC架…...

【C++初阶】vector

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…...

elasticsearch 和 RediSerch

elasticsearch 和 RediSerch 前情提要 学习文章来自Docker 安装 ElasticSearch - 知乎 (zhihu.com) docker 安装 docker pull docker.io/elasticsearch:7.1.1启动! docker run -d --name es -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" b0e9f9f0…...

删除MySQL中所有表的外键

方法一&#xff1a; 原理 查询schema中所有外键名称然后拼接生成删除语句 第一步&#xff1a; SELECT CONCAT(ALTER TABLE ,TABLE_SCHEMA,.,TABLE_NAME, DROP FOREIGN KEY ,CONSTRAINT_NAME, ;) FROM information_schema.TABLE_CONSTRAINTS c WHERE c.TABLE_SCHEMA数据库名…...

webstorm新建vue项目相关问题

前言 这个迭代后端需求偏少&#xff0c;前端code的键盘都起火星子了。来了4个外包支持&#xff0c;1个后端3个前端&#xff0c;还是不够用啊。刚好趁这个机会稍微学习下vue&#xff0c;其实之前环境也配置过了&#xff0c;所以这里就不分享环境配置了&#xff0c;主要分享下新建…...

2024年高考考务人员网上培训参考答案

第1部分&#xff1a;单选题 1. 关于试卷保密室负责人职责&#xff0c;以下说法不正确的是&#xff08;B&#xff09; [2分] A. 负责试卷的接收、保管和发放工作 B. 试卷保密室内屋门锁钥匙和铁柜门锁钥匙必须由同一人保管 C. 试卷接收和发放应当当面清点试卷袋数量&#…...

JavaEE之线程(9) _定时器的实现代码

前言 定时器也是软件开发中的一个重要组件. 类似于一个 “闹钟”。 达到一个设定的时间之后&#xff0c;就执行某个指定好的代码&#xff0c;比如&#xff1a; 在受上述场景中&#xff0c;当客户端发出去请求之后&#xff0c; 就要等待响应&#xff0c;如果服务器迟迟没有响应&…...

纯前端实现将页面数据下载word文档中【包括图片,echarts图,表格,和对话 内容】

亲测真实有效 导出word步骤 在Vue中导出Word文档&#xff0c;可以使用第三方库file-saver和html-docx-js。首先需要安装这两个库&#xff1a; npm install file-saver html-docx-js --save "html-docx-js": "0.3.1","file-saver": "2.0.5…...

JavaSE——类和对象(二)~~封装

目录 一.封装 二.封装扩展之包 三.static成员 四. 代码块 五. 内部类&#xff08;重要&#xff09; 大家好呀&#xff0c;我是北纬&#xff0c;接着上节我们继续讲解Java中关于类和对象的相关知识&#xff0c;今天着重给大家介绍一下关于面向对象程序的特性之一——封装。…...

头歌OpenGauss数据库-I.复杂查询第9关:交换性别

任务描述 本关任务&#xff1a;给定一张 tb_Salary 表&#xff0c;如下所示&#xff0c;有 m 男性 和 f 女性的值。交换所有的 f 和 m 值&#xff08;例如&#xff0c;将所有 f 值更改为 m&#xff0c;反之亦然&#xff09;。 idnamesexsalary1Elonf70002Donnyf80003Careym60…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...