咱们工作在和其余组织配合时,咱们可能不是作为服务器搭建的一方,而是属于客户端的一方,须要去获取服务器的组织构造,依照某些条件去获取服务器的数据,也能够是同步组织构造

尽管说 golang 的数据结构没有 c++ 那么丰盛,不过对于这个 ldap 还是有相应的库来进行解决的

官网文档地址:https://pkg.go.dev/gopkg.in/ldap.v3

咱们也能够下载 github 下面的这个库

go get github.com/go-ldap/ldap/v3

golang 对于 ldap 库最新的版本是 Version: v3.1.0

开始编码

咱们来写一个 demo ,获取咱们上次搭建的 ldap 服务器上的组织构造

这是咱们简略搭建的 ldap 服务器,能够应用 LDAP Admin 可视化管理工具来查看具体的页面成果

咱们把这个库下载下来后,咱们的编码思路如下:

  • 填写 ldap 服务器地址以及填写相应的管理员信息,与 ldap 服务器建设连贯
  • 编写查问申请,并开始向 ldap 服务器进行查问
  • 将查问构造,依照 ldap v3 库提供的形式 打印出成果来

连贯 服务器

咱们能够应用 func DialURL(addr string, opts ...DialOpt) (*Conn, error) 函数来与 ldap 服务器建设连贯

ml, err := ldap.DialURL("ldap://xxxx")    if err != nil {        log.Fatal(err)    }    defer ml.Close()

咱们填入的地址中,能够不必输出端口号,库函数曾经有给咱们做好解决,咱们能够来看看源码

DialURL 函数用于连贯 ldap 服务器,连贯胜利会给咱们返回一个新的连贯

咱们能够持续看一下这个函数调用 c, err := dc.dial(u)

golang 的库会依据咱们填写的地址是 ldap 还是 ldaps 来判断是做加密传输还是不加密传输,与之对应的就是拜访不加密的用 389 端口加密的就应用 636 端口

增加管理员绑定信息

咱们增加的 ldap 域信息为:dc=xiaomotong,dc=com

我的管理员是:cn=admin,dc=xiaomotong,dc=com

_, err = ml.SimpleBind(&ldap.SimpleBindRequest{        Username: "cn=admin,dc=xiaomotong,dc=com",        Password: "123123",    })    if err != nil {        log.Fatalf("Failed to bind: %s\n", err)    }    fmt.Println("connect successfully !!")

来看看理论的 SimpleBindRequest 数据结构

// SimpleBindRequest represents a username/password bind operationtype SimpleBindRequest struct {    // Username is the name of the Directory object that the client wishes to bind as    Username string    // Password is the credentials to bind with    Password string    // Controls are optional controls to send with the bind request    Controls []Control    // AllowEmptyPassword sets whether the client allows binding with an empty password    // (normally used for unauthenticated bind).    AllowEmptyPassword bool}
  • Username
  • Password

客户端须要绑定的域用户和明码

  • Controls

须要绑定申请的控件

  • AllowEmptyPassword

是否容许空明码,若是空明码,个别是绑定一个未受权的用户

编写查问申请,并开始查问 ldap 服务器

searchRequest := ldap.NewSearchRequest(        "dc=xiaomotong,dc=com",        ldap.ScopeWholeSubtree,        ldap.NeverDerefAliases,        0,        0,        false,        "(ou=People)",        []string{},        nil,    )    searchResult, err := ml.Search(searchRequest)    if err != nil {        log.Println("can't search ", err.Error())    }    log.Printf("%d", len(searchResult.Entries))

编写查问申请,也就是简略的给咱们的构造体进行一个负值操作,填写好对相应的参数,即可开始查问,一起来看看这个构造体NewSearchRequest

基本上就是填写相应的域信息

  • BaseDN , 一个域惟一的标识
  • scope 范畴的抉择,咱们默认抉择ScopeWholeSubtree ,查问所有的子树
  • DerefAliases , SizeLimit,TimeLimit,TypesOnly 填写默认值即可
  • Filter , 查问须要的过滤条件,能够依照咱们的理论状况写条件,就像写查询数据库的条件一样,这里不能为空,否则会程序解体
F:\codegitee\golang_study\later_learning\ldap_test>go run main.goconnect successfully !!2021/11/06 21:07:59 can't search  LDAP Result Code 201 "Filter Compile Error": ldap: error parsing filterpanic: runtime error: invalid memory address or nil pointer dereference[signal 0xc0000005 code=0x0 addr=0x4 pc=0xa33cef]goroutine 1 [running]:main.main()        F:/codegitee/golang_study/later_learning/ldap_test/main.go:40 +0x24fexit status 2
  • Attributes , 须要返回的属性有哪些,是一个切片,如果咱们默认填空,则会返回所有属性

查看对应的 Search 函数源码

代码的大抵逻辑是,doRequest 将数据组包向 ldap 服务器发送申请,申请胜利之后,将响应的数据依照 tag 不同的内容进行解析

最终返回一个 *SearchResult 查问后果的指针

输出查问信息

for _, item := range searchResult.Entries {   item.Print()   fmt.Printf("\n\n")}

上图源码咱们能够看到输入查问信息就是遍历一下 searchResult.Entries ,咱们能够来看看对应的数据结构

咱们能够看到后果外面,有一个 Entries []*Entry 是一个切片,外面放了多个 *Entry , 在 ldap 服务器中, 1 个 Entry 就代表一条惟一的记录

Entry 构造体就是对应的 DN,一条记录惟一的分别名 , 和他波及的属性

EntryAttribute 属性构造体中,咱们能够看到 有 Name ,有 Values ,这里就是对应咱们之前说到的 RDN,也就是一个键值对,多个键值对组成一个 DN

最终咱们来查看一下成果

>go run main.goconnect successfully !!2021/11/06 21:20:58 1DN: ou=People,dc=xiaomotong,dc=comobjectClass: [organizationalUnit]ou: [People]

后果是输入了 1 条信息,没错,因为咱们的 ou=people 只有 1条记录,如果咱们须要查问整个 ldap服务器的所有数据,则咱们能够将上述代码的 Filter 地位,批改成 objectClass=*

解释上述后果:

  • DN 示意惟一的记录,是分别名的意思
  • objectClass 是一个类,这里对应的是 organizationalUnit ,示意组织单元OU,能够了解为 组
  • ou: [People] 指的是这个 ou 对应的名字是 People

欢送点赞,关注,珍藏

敌人们,你的反对和激励,是我保持分享,提高质量的能源

好了,本次就到这里

技术是凋谢的,咱们的心态,更应是凋谢的。拥抱变动,背阴而生,致力向前行。

我是阿兵云原生,欢送点赞关注珍藏,下次见~