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:java: 无法访问org.springframework.ldap.core.LdapTemplate易错点2:java: 无法访问org.springframework.context.ConfigurableApplicationContext易错点3:[LDAP: error…...
openjudge_2.5基本算法之搜索_2990:符号三角形
题目 2990:符号三角形 总时间限制: 1000ms 内存限制: 65536kB 描述 符号三角形的第1行有n个由“”和”-“组成的符号 ,以后每行符号比上行少1个,2个同号下面是”“,2个异号下面是”-“ 。计算有多少个不同的符号三角形,使其所含”…...

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

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

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

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

每日一题《leetcode--398.随机数索引》
https://leetcode.cn/problems/random-pick-index/ 根据题目所知,所给的数组中有重复的元素。让我们随机输出给定的目标数字的下标索引。 typedef struct {int *sum;int length; } Solution;Solution* solutionCreate(int* nums, int numsSize) {Solution* obj (So…...
【MySQL精通之路】MySQL的使用(9)-设置环境变量
可以在命令提示符下设置环境变量,以影响命令处理器的当前调用,也可以永久设置环境变量以影响未来的调用。 要永久设置变量,可以在启动文件中进行设置,也可以使用系统为此提供的接口进行设置。 有关具体细节,请参阅命…...

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 是在分布式系统(进程的隔离性:Redis 就是基于网络,可以把自己内存中的变量给别的进程…...

基于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
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ 🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿…...

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中所有表的外键
方法一: 原理 查询schema中所有外键名称然后拼接生成删除语句 第一步: 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项目相关问题
前言 这个迭代后端需求偏少,前端code的键盘都起火星子了。来了4个外包支持,1个后端3个前端,还是不够用啊。刚好趁这个机会稍微学习下vue,其实之前环境也配置过了,所以这里就不分享环境配置了,主要分享下新建…...
2024年高考考务人员网上培训参考答案
第1部分:单选题 1. 关于试卷保密室负责人职责,以下说法不正确的是(B) [2分] A. 负责试卷的接收、保管和发放工作 B. 试卷保密室内屋门锁钥匙和铁柜门锁钥匙必须由同一人保管 C. 试卷接收和发放应当当面清点试卷袋数量&#…...

JavaEE之线程(9) _定时器的实现代码
前言 定时器也是软件开发中的一个重要组件. 类似于一个 “闹钟”。 达到一个设定的时间之后,就执行某个指定好的代码,比如: 在受上述场景中,当客户端发出去请求之后, 就要等待响应,如果服务器迟迟没有响应&…...
纯前端实现将页面数据下载word文档中【包括图片,echarts图,表格,和对话 内容】
亲测真实有效 导出word步骤 在Vue中导出Word文档,可以使用第三方库file-saver和html-docx-js。首先需要安装这两个库: npm install file-saver html-docx-js --save "html-docx-js": "0.3.1","file-saver": "2.0.5…...

JavaSE——类和对象(二)~~封装
目录 一.封装 二.封装扩展之包 三.static成员 四. 代码块 五. 内部类(重要) 大家好呀,我是北纬,接着上节我们继续讲解Java中关于类和对象的相关知识,今天着重给大家介绍一下关于面向对象程序的特性之一——封装。…...
头歌OpenGauss数据库-I.复杂查询第9关:交换性别
任务描述 本关任务:给定一张 tb_Salary 表,如下所示,有 m 男性 和 f 女性的值。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。 idnamesexsalary1Elonf70002Donnyf80003Careym60…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Pydantic + Function Calling的结合
1、Pydantic Pydantic 是一个 Python 库,用于数据验证和设置管理,通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发(如 FastAPI)、配置管理和数据解析,核心功能包括: 数据验证:通过…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
基于Uniapp的HarmonyOS 5.0体育应用开发攻略
一、技术架构设计 1.混合开发框架选型 (1)使用Uniapp 3.8版本支持ArkTS编译 (2)通过uni-harmony插件调用原生能力 (3)分层架构设计: graph TDA[UI层] -->|Vue语法| B(Uniapp框架)B --&g…...

spring boot使用HttpServletResponse实现sse后端流式输出消息
1.以前只是看过SSE的相关文章,没有具体实践,这次接入AI大模型使用到了流式输出,涉及到给前端流式返回,所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...