Spring Boot 连接LDAP的方法

时间:2022-07-04 00:01:13

本文是spring boot系列文集中关于ldap连接相关操作的一文。仅仅涉及基本的使用odm来快速实现ldap增删改查操作。详细的关于spring ldap的其他操作,可以参考翻译的官方文档。

本文目的:使用spring boot构建项目,帮助读者快速配置并使用spring ldap操作ldap。大致步骤如下:

1.创建spring boot项目(约1分钟)

 2.添加pom.xml文件中spring ldap依赖(约1分钟)

3.配置spring ldap连接信息(约1分钟)

4.创建实体类作为ldap中的entry映射(odm映射功能,类似orm)

5.使用ldaptemplate书写service层的方法(约3分钟)

6.编写controller层(约3分钟)

1.创建spring boot项目(约1分钟)

idea中点击file - new - project

Spring Boot 连接LDAP的方法

图1

如上图,选择左侧的 spring initializr帮助初始化spring项目,配置好sdk后,点击next。

Spring Boot 连接LDAP的方法

图2

点击后,如图2,如果只是做demo,该页面默认即可,点击next。

Spring Boot 连接LDAP的方法

图3

如图3,我们选择web,右侧会显示web相关的组件,我们选择右侧中的web,将其前面的框勾选上。这代表在创建的spring boot项目中会引入web相关的依赖。点击next。

Spring Boot 连接LDAP的方法

图4

如图4,这里自己命名即可,点击finish。

2.添加pom.xml文件中spring ldap依赖(约1分钟)

Spring Boot 连接LDAP的方法

图5

如上图图5,在项目中双击pom.xml来添加依赖。

Spring Boot 连接LDAP的方法

图6

如图6所示,文件中已经加载了spring-boot-starter-web依赖,我们要使用spring ldap来操作ldap服务器需要添加spring-boot-starter-data-ldap。该依赖会自动加载spring-ldap-core 与 spring-data-ldap依赖。其中spring-ldap-core是ldap操作的核心依赖,而spring-data-ldap提供了odm的功能,能够简化操作。我们可以在项目的external libraries中看到这两个依赖,如下图图7中三个黄色高亮处:

Spring Boot 连接LDAP的方法

图7

3.配置spring ldap连接信息

Spring Boot 连接LDAP的方法

图8

如上图图8,根据spring boot官网对ldap配置的说明来配置,可以看这里。这样配置之后,spring boot会自动读取该配置。

4.创建实体类作为ldap中的entry映射

本例中使用odm功能,极大的简化了ldap的操作,关于odm更多的信息,可以参考翻译的官方文档。

我们在项目中创建如下结构:

Spring Boot 连接LDAP的方法

图9

现在,我们在entry包下写与entry互相映射的实体类。其中,我的ldap结构如下

Spring Boot 连接LDAP的方法

图10

新建person类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.example.demo.entry;
import com.fasterxml.jackson.annotation.jsonignore;
import org.springframework.ldap.odm.annotations.attribute;
import org.springframework.ldap.odm.annotations.entry;
import org.springframework.ldap.odm.annotations.id;
import org.springframework.ldap.support.ldapnamebuilder;
import javax.naming.name;
/**
 * @author: geng_pool
 * @description:
 * @date: created in 2017/12/27 10:24
 * @modified by:
 */
@entry(objectclasses = {"organizationalperson","person","top"},base = "o=myorg")
public class person {
 @id
 @jsonignore
 private name dn;
 
 @attribute(name="cn")
 private string cn;
 
 @attribute(name="sn")
 private string sn;
 
 @attribute(name="userpassword")
 private string userpassword;
 
 public person(string cn) {
  name dn = ldapnamebuilder.newinstance()
    .add("o", "myorg")
    .add("cn", cn)
    .build();
  this.dn = dn;
 }
 public person(){}
 
 /* getter */
 public name getdn() {
  return dn;
 }
 
 public string getcn() {
  return cn;
 }
 
 public string getsn() {
  return sn;
 }
 
 public string getuserpassword() {
  return userpassword;
 }
 
 /* setter */
 public void setdn(name dn) {
  this.dn = dn;
 }
 
 public void setcn(string cn) {
  this.cn = cn;
  if(this.dn==null){
   name dn = ldapnamebuilder.newinstance()
     .add("o", "myorg")
     .add("cn", cn)
     .build();
   this.dn = dn;
  }
 }
 
 public void setsn(string sn) {
  this.sn = sn;
 }
 
 public void setuserpassword(string userpassword) {
  this.userpassword = userpassword;
 }
 
 @override
 public string tostring() {
  return "person{" +
    "dn=" + dn.tostring() +
    ", cn='" + cn + '\'' +
    ", sn='" + sn + '\'' +
    ", userpassword='" + userpassword + '\'' +
    '}';
 }
}

注意@entry与@id为必须的。而@jsonignore是为了将person传给前端时不报错,因为name类型的无法自动解析成json格式。注意我为了方便,在 public person(string cn) {}构造方法中写上了dn值的生成方法,在setcn中也写上了该方法,当然存在代码重复问题,忽略就好。

5.使用ldaptemplate书写service层的方法

在service包中,新建odmpersonrepo类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.example.demo.service;
import com.example.demo.entry.person;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.ldap.core.ldaptemplate;
import org.springframework.stereotype.service;
import static org.springframework.ldap.query.ldapquerybuilder.query;
 
/**
 * @author: geng_pool
 * @description:
 * @date: created in 2017/12/27 10:37
 * @modified by:
 */
@service
public class odmpersonrepo {
 
 @autowired
 private ldaptemplate ldaptemplate;
 
 public person create(person person){
  ldaptemplate.create(person);
  return person;
 }
 
 public person findbycn(string cn){
  return ldaptemplate.findone(query().where("cn").is(cn),person.class);
 }
 
 public person modifyperson(person person){
  ldaptemplate.update(person);
  return person;
 }
 
 public void deleteperson(person person){
  ldaptemplate.delete(person);
 }
 
}

可以看到,基本的增删改查操作都帮我们实现了,我们只要调用一下ldaptemplate中的方法即可。若要更*的操作ldap的增删改查,可参阅翻译的官方文档。

6.编写controller层

在controller包下,新建一个testcontroller类来测试ldap的操作。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.example.demo.controller;
 
import com.example.demo.entry.person;
import com.example.demo.service.odmpersonrepo;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.ldap.core.ldaptemplate;
import org.springframework.web.bind.annotation.*;
 
/**
 * @author: geng_pool
 * @description:
 * @date: created in 2017/12/27 10:50
 * @modified by:
 */
@restcontroller
public class testcontroller {
 @autowired
 private odmpersonrepo odmpersonrepo;
 
 @requestmapping(value = "/findone",method = requestmethod.post)
 public person findbycn(@requestparam(name = "cn",required = true) string cn){
  return odmpersonrepo.findbycn(cn);
 }
 
 @postmapping(value = "/create")
 public person create(@requestparam(name = "cn") string cn,@requestparam(name = "sn") string sn,@requestparam(name = "userpassword") string userpassworld){
  person person = new person();
  person.setcn(cn);
  person.setsn(sn);
  person.setuserpassword(userpassworld);
  return odmpersonrepo.create(person);
 }
 
 
 
 @postmapping(value = "/update")
 public person update(@requestparam(name = "cn") string cn,@requestparam(name = "sn") string sn,@requestparam(name = "userpassword") string userpassworld){
  person person = new person();
  person.setcn(cn);
  person.setsn(sn);
  person.setuserpassword(userpassworld);
  return odmpersonrepo.modifyperson(person);
 }
 
 @postmapping(value = "/delete")
 public void delete(@requestparam(name = "cn")string cn){
  person person = new person();
  person.setcn(cn);
  odmpersonrepo.deleteperson(person);
 }
 
}

至此,一个基本的demo完成啦。下面我们测试一下

测试

为了大家都能跟着步骤来,我就不使用postman来测试,而是在浏览器中测试接口。、

启动spring boot,没有报错的话,打开浏览器到 localhost:8080/ ,按下f12,弹出开发者模式,找到console控制台方便我们发送测试语句。

首先,引入jquery.js。打开jquery.js,全选-复制-在console中粘贴-回车,如下图:

Spring Boot 连接LDAP的方法

图11

显示为true,代表加载成功,我们可以使用jquery的ajax来测试了。

新增数据

Spring Boot 连接LDAP的方法

图12

正如controller层的testcontroller要求的那样,我们在地址 /create 上使用post方法,将数据cn sn userpassword传过去

Spring Boot 连接LDAP的方法

图13

而在ldap服务器中,也显示了新增的数据

Spring Boot 连接LDAP的方法

图14

查找数据

Spring Boot 连接LDAP的方法

图15

也能根据cn正确查找到数据。

修改数据

Spring Boot 连接LDAP的方法

图16

我们查看ldap中是否修改

Spring Boot 连接LDAP的方法

图17

可以看到能够正常修改数据

删除数据

 Spring Boot 连接LDAP的方法

图18

查看ldap中是否删除

Spring Boot 连接LDAP的方法

图19

可以看到,数据被正确删除了。

其他说明

  1. 刚才的例子中,代码有需要完善的地方,但对于demo演示来说完全可以忍受。大家可能也看到了这么做也有些缺点,我在update的时候,需要将修改后的person的所有属性值都传到后台来(这也不算啥缺点,关系数据库的更新也是这样),并且不能修改cn的值(这就是为什么其他例子中都是使用uid来作为dn的一部分,类似于关系数据库的主键的作用),因为修改后该entry的dn值就变化了,odm就无法确定更新哪个数据。会报 javax.naming.namenotfoundexception: [ldap: error code 32 - no such object] 错误。
  2. 删除操作也像关系数据库的操作一样,直接给cn即可,这是因为我们在person类中setcn()方法内写了dn的生成函数,这样odm才能根据被@id所注释的dn来找到ldap中的entry并执行删除操作。
  3. 我们在person类中写了name类型的dn值的构建方法,但是我一开始按照官网的代码来写,总是出问题,在*中找到了答案。链接在这里。
  4. 想要更深入的了解,可以参考翻译的官方文档。了解更*更个性化的操作。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://www.jianshu.com/p/316fbb6bfd81