文章目录
- 一、项目背景
- 二、准备工作
- 三、验证结果
- 四、易错点讲解
- 易错点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 目录时的起始位置。