1. 新建一个 SpringBoot 项目测试环境:
SpringBoot: 2.4.0
Window Server: 2012R2
Ldap browser: Softerra LDAP Administrator 2021.1 (32-bit)
附带 Spring LDAP 文档 官网文档
添加 LDAP 依赖包
2. 配置 LDAP 连接org.springframework.boot spring-boot-starter-data-ldap
在 application.yml中配置
注意下面对应的 dc 等信息均以 a,b 字符代替,使用时替换成项目的地址即可
spring:
ldap:
urls: ldap://a.b.com:389
username: c@b.com
password: xxxxxxxxx
base: dc=b,dc=com
3. 添加数据接口
3.1 创建 AD 用户实例类
@Data
@Entry(base = "dc=b,dc=com", objectClasses = "user")
public class Person {
@Id
private Name id;
@Attribute(name = "cn")
private String cn;
@Attribute(name = "sn")
private String sn;
@Attribute(name="mail")
private String mail;
@Attribute(name="telephoneNumber")
private String telephoneNumber;
@Attribute(name="description")
private String description;
@Attribute(name="givenName")
private String givenName;
}
3.2 创建一个 PersonReposity 数据接口
public interface PersonRepository extends LdapRepository3.3 测试接口{}
下面测试获取用户、验证接口
- 获取所有用户信息
personRepository.findAll().forEach(System.out::pringln)
打印结果(这里屏蔽了部分敏感信息就不展示了)
Person(id=CN=Administrator,CN=Users, cn=Administrator, sn=null, mail=null, telephoneNumber=null, description=***, givenName=null) Person(id=CN=Guest,CN=Users, cn=Guest, sn=null, mail=null, telephoneNumber=null, description=****, givenName=null) Person(id=CN=***,CN=Users, cn=Alan, sn=null, mail=null, telephoneNumber=null, description=null, givenName=null) Person(id=CN=***,OU=Domain Controllers, cn=***, sn=null, mail=null, telephoneNumber=null, description=null, givenName=null) Person(id=CN=***,CN=Users, cn=krbtgt, sn=null, mail=null, telephoneNumber=null, description=***, givenName=null) Person(id=CN=***,CN=Users, cn=huangalan, sn=huang, mail=null, telephoneNumber=null, description=null, givenName=alan) Person(id=CN=a,CN=Users, cn=a, sn=a, mail=test@123.com, telephoneNumber=123123123123123, description=teststsetsetsetsetsetset, givenName=a-name)
- 获取单个用户信息
以上面的 cn=a用户为例
personRepository.findOne(query().where("cn").is("a"), Person.class);
打印结果:
Person(id=CN=a,CN=Users, cn=a, sn=a, mail=test@123.com, telephoneNumber=123123123123123, description=teststsetsetsetsetsetset, givenName=a-name)
- 验证用户账户
这里以 cn=a为例,传入用户名和密码测试
String password = "123456";
String username = "a";
personRepository.authenticate(query().where("cn").is(username ), password ,
(dirContext, ldapEntryIdentification) ->
ldapTemplate.findOne(query().where(attribute).is(username), Person.class));
打印结果:
Person(id=CN=a,CN=Users, cn=a, sn=a, mail=test@123.com, telephoneNumber=123123123123123, description=teststsetsetsetsetsetset, givenName=a-name)
LdapRepository 已经封装了很多操作用户接口,这里就不一一测试了,有兴趣的童鞋可以自己测试,诸如:
delete() deleteAll() findById() existById() .... 直接调用即可4. 整合封装
将上面接口整合成一个 service
public interface LdapService {
Iterable findAllPersons();
Person findOnePerson(String attribute, String value);
Person authenticate(String attribute, String username, String password);
}
@Service
@Slf4j
public class LdapServiceImpl implements LdapService {
private final LdapTemplate ldapTemplate;
private final PersonRepository personRepository;
@Autowired
public LdapServiceImpl(LdapTemplate ldapTemplate, PersonRepository personRepository) {
this.ldapTemplate = ldapTemplate;
this.personRepository = personRepository;
}
@Override
public Iterable findAllPersons() {
return personRepository.findAll();
}
@Override
public Person findOnePerson(String attribute, String value) {
try {
return ldapTemplate.findOne(query().where(attribute).is(value), Person.class);
} catch (EmptyResultDataAccessException e) {
log.error("Found 0 result, error: {}", e.getMessage());
}
return null;
}
@Override
public Person authenticate(String attribute, String username, String password) {
return ldapTemplate.authenticate(
query().where(attribute).is(username),
password,
(dirContext, ldapEntryIdentification) ->
ldapTemplate.findOne(query().where(attribute).is(username), Person.class));
}
}
整合完毕 !!
5. 可能遇到的问题PartialResultException: Unprocessed Continuation Reference(s); remaining name '/'
这个是 AD 无法进行自动处理引用的原因,解决方法:忽略这个异常,设置 setIgnorePartialResultException 为 true
@Autowired private final LdapTemplate ldapTemplate; ...... ldapTemplate.setIgnorePartialResultException(true);
AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903C5, comment: AcceptSecurityContext error, data 52e, v2580
这个错误一般是上面第二步配置 yml 的 username 不正确造成
spring:
ldap:
urls: ldap://a.b.com:389
## 这里出错
username: c@b.com
password: xxxxxxxxx
base: dc=b,dc=com
解决方法:
username 配置方式推荐这两种
- 属性配置形式:CN=a,CN=Users,DC=b,DC=com
- 域名形式: a@b.com a 为登陆用户名,b.com 是上面配置的 dc=b,dc=com 组合
推荐 LDAP browser :Softerra LDAP Administrat, 官网下载地址
附带简单教程
安装的话直接一路 next 即可,中间可配置安装路径
安装完成后打开软件连接 LDAP
- 新建一个 Profile
输入连接名称,随便输即可
- 连接参数配置
Host 是 AD 域的连接地址,例如域 ADtest 和 IP 地址都可以,端口默认 389
base dn 这些信息可以从AD ACSI管理器查看,然后点击下一步
这里是输入连接凭证的,Principal Password 输入 yml 中配置的 username 和 password 点击下一步即可,等待验证链接完成就可以查看所有用的信息啦



